Files
libreoffice/vcl/win/source/window/salframe.cxx

5180 lines
187 KiB
C++
Raw Normal View History

2000-09-18 16:07:07 +00:00
/*************************************************************************
*
* $RCSfile: salframe.cxx,v $
*
* $Revision: 1.85 $
2000-09-18 16:07:07 +00:00
*
* last change: $Author: ssa $ $Date: 2002-11-26 16:37:42 $
2000-09-18 16:07:07 +00:00
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (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.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#include <string.h>
#include <limits.h>
#ifdef DBG_UTIL
#include <stdio.h>
#endif
#ifndef _SVWIN_HXX
#include <tools/svwin.h>
#endif
#define _SV_SALFRAME_CXX
#ifndef _RTL_STRING_H_
#include <rtl/string.h>
#endif
#ifndef _RTL_USTRING_H_
#include <rtl/ustring.h>
#endif
2000-09-18 16:07:07 +00:00
#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif
#define private public
#ifndef _SV_WINCOMP_HXX
#include <wincomp.hxx>
#endif
#ifndef _SV_SALIDS_HRC
#include <salids.hrc>
#endif
#ifndef _SV_SYSDATA_HXX
#include <sysdata.hxx>
#endif
#ifndef _SV_SALDATA_HXX
#include <saldata.hxx>
#endif
#ifndef _SV_SALINST_HXX
#include <salinst.hxx>
#endif
2001-08-23 12:45:29 +00:00
#ifndef _SV_SALBMP_HXX
#include <salbmp.hxx>
#endif
2000-09-18 16:07:07 +00:00
#ifndef _SV_SALGDI_HXX
#include <salgdi.hxx>
#endif
#ifndef _SV_SALSYS_HXX
#include <salsys.hxx>
#endif
#ifndef _SV_SALFRAME_HXX
#include <salframe.hxx>
#endif
#ifndef _SV_SALVD_HXX
#include <salvd.hxx>
#endif
#ifndef _SV_TIMER_HXX
#include <timer.hxx>
#endif
#ifndef _SV_SETTINGS_HXX
#include <settings.hxx>
#endif
#ifndef _SV_KEYCOES_HXX
#include <keycodes.hxx>
#endif
2001-11-23 11:39:27 +00:00
#ifndef _SV_WINDOW_H
#include <window.h>
#endif
#ifndef _SV_WINDOW_HXX
#include <window.hxx>
#endif
#ifndef _SV_WRKWIN_HXX
#include <wrkwin.hxx>
#endif
2002-07-11 06:43:29 +00:00
#ifndef _SV_SALLAYOUT_HXX
#include <sallayout.hxx>
#endif
2002-09-18 15:35:23 +00:00
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
2002-05-08 10:09:33 +00:00
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
// misssing prototypes and constants for LayeredWindows
extern "C" {
WINUSERAPI BOOL WINAPI SetLayeredWindowAttributes(HWND,COLORREF,BYTE,DWORD);
};
#define LWA_COLORKEY 0x00000001
#define LWA_ALPHA 0x00000002
#define ULW_COLORKEY 0x00000001
#define ULW_ALPHA 0x00000002
#define ULW_OPAQUE 0x00000004
#define WS_EX_LAYERED 0x00080000
2000-09-18 16:07:07 +00:00
// =======================================================================
// Wegen Fehler in Windows-Headerfiles
#ifndef IMN_OPENCANDIDATE
#define IMN_OPENCANDIDATE 0x0005
#endif
#ifndef IMN_CLOSECANDIDATE
#define IMN_CLOSECANDIDATE 0x0004
#endif
// =======================================================================
BOOL SalFrame::mbInReparent = FALSE;
static void UpdateFrameGeometry( HWND hWnd, SalFrame* pFrame );
2000-09-18 16:07:07 +00:00
static void ImplSaveFrameState( SalFrame* pFrame )
{
// Position, Groesse und Status fuer GetWindowState() merken
if ( !pFrame->maFrameData.mbFullScreen )
{
BOOL bVisible = (GetWindowStyle( pFrame->maFrameData.mhWnd ) & WS_VISIBLE) != 0;
if ( IsIconic( pFrame->maFrameData.mhWnd ) )
{
pFrame->maFrameData.maState.mnState |= SAL_FRAMESTATE_MINIMIZED;
if ( bVisible )
pFrame->maFrameData.mnShowState = SW_SHOWMAXIMIZED;
}
else if ( IsZoomed( pFrame->maFrameData.mhWnd ) )
{
pFrame->maFrameData.maState.mnState &= ~SAL_FRAMESTATE_MINIMIZED;
pFrame->maFrameData.maState.mnState |= SAL_FRAMESTATE_MAXIMIZED;
if ( bVisible )
pFrame->maFrameData.mnShowState = SW_SHOWMAXIMIZED;
pFrame->maFrameData.mbRestoreMaximize = TRUE;
}
else
{
RECT aRect;
GetWindowRect( pFrame->maFrameData.mhWnd, &aRect );
// to be consistent with Unix, the frame state is without(!) decoration
RECT aRect2 = aRect;
AdjustWindowRectEx( &aRect2, GetWindowStyle( pFrame->maFrameData.mhWnd ),
FALSE, GetWindowExStyle( pFrame->maFrameData.mhWnd ) );
long nTopDeco = abs( aRect.top - aRect2.top );
long nLeftDeco = abs( aRect.left - aRect2.left );
long nBottomDeco = abs( aRect.bottom - aRect2.bottom );
long nRightDeco = abs( aRect.right - aRect2.right );
2000-09-18 16:07:07 +00:00
pFrame->maFrameData.maState.mnState &= ~(SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED);
// subtract decoration
pFrame->maFrameData.maState.mnX = aRect.left+nLeftDeco;
pFrame->maFrameData.maState.mnY = aRect.top+nTopDeco;
pFrame->maFrameData.maState.mnWidth = aRect.right-aRect.left-nLeftDeco-nRightDeco;
pFrame->maFrameData.maState.mnHeight = aRect.bottom-aRect.top-nTopDeco-nBottomDeco;
2000-09-18 16:07:07 +00:00
if ( bVisible )
pFrame->maFrameData.mnShowState = SW_SHOWNORMAL;
pFrame->maFrameData.mbRestoreMaximize = FALSE;
}
}
}
2002-05-08 10:09:33 +00:00
// -----------------------------------------------------------------------
2002-11-20 16:15:33 +00:00
// if pParentRect is set, the workarea of the monitor that contains pParentRect is returned
static void ImplSalGetWorkArea( HWND hWnd, RECT *pRect, const RECT *pParentRect )
2002-05-08 10:09:33 +00:00
{
static int winVerChecked = 0;
static int winVerOk = 0;
// check if we or our parent is fullscreen, then the taskbar should be ignored
bool bIgnoreTaskbar = false;
SalFrame* pFrame = GetWindowPtr( hWnd );
if( pFrame )
{
Window *pWin = ((Window*)pFrame->maFrameData.mpInst);
while( pWin )
{
WorkWindow *pWorkWin = (pWin->GetType() == WINDOW_WORKWINDOW) ? (WorkWindow *) pWin : NULL;
if( pWorkWin && pWorkWin->mbReallyVisible && pWorkWin->mbFullScreenMode )
{
bIgnoreTaskbar = true;
break;
}
else
pWin = pWin->mpParent;
}
}
2002-05-08 10:09:33 +00:00
if( !winVerChecked )
{
winVerChecked = 1;
winVerOk = 1;
// multi monitor calls not available on Win95/NT
OSVERSIONINFO aVerInfo;
aVerInfo.dwOSVersionInfoSize = sizeof( aVerInfo );
if ( GetVersionEx( &aVerInfo ) )
{
if ( aVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
if ( aVerInfo.dwMajorVersion <= 4 )
winVerOk = 0; // NT
}
else if( aVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
if ( aVerInfo.dwMajorVersion == 4 && aVerInfo.dwMinorVersion == 0 )
winVerOk = 0; // Win95
}
}
}
// calculates the work area taking multiple monitors into account
if( winVerOk )
{
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
SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 );
}
2002-05-08 10:09:33 +00:00
else
{
2002-11-20 16:15:33 +00:00
if( pParentRect != NULL )
{
2002-11-20 16:15:33 +00:00
// 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;
SystemParametersInfo( 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;
}
}
2002-05-08 10:09:33 +00:00
}
}
else
{
if( bIgnoreTaskbar )
{
pRect->left = pRect->top = 0;
pRect->right = GetSystemMetrics( SM_CXSCREEN );
pRect->bottom = GetSystemMetrics( SM_CYSCREEN );
}
else
SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 );
}
2002-05-08 10:09:33 +00:00
}
2000-09-18 16:07:07 +00:00
// =======================================================================
SalFrame* ImplSalCreateFrame( SalInstance* pInst,
HWND hWndParent, ULONG nSalFrameStyle )
{
SalFrame* pFrame = new SalFrame;
HWND hWnd;
DWORD nSysStyle = 0;
DWORD nExSysStyle = 0;
BOOL bSubFrame = FALSE;
2000-09-18 16:07:07 +00:00
static int bLayeredAPI = -1;
if( bLayeredAPI == -1 )
{
bLayeredAPI = 0;
OSVERSIONINFO aVerInfo;
aVerInfo.dwOSVersionInfoSize = sizeof( aVerInfo );
if ( GetVersionEx( &aVerInfo ) )
// check for W2k and XP
if ( aVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aVerInfo.dwMajorVersion >= 5 )
bLayeredAPI = 1;
}
static const char* pEnvTransparentFloats = getenv("SAL_TRANSPARENT_FLOATS" );
2000-09-18 16:07:07 +00:00
// determine creation data
if ( nSalFrameStyle & SAL_FRAME_STYLE_CHILD )
nSysStyle |= WS_CHILD;
else
{
if ( hWndParent )
{
nSysStyle |= WS_POPUP;
bSubFrame = TRUE;
pFrame->maFrameData.mbNoIcon = TRUE;
}
else
{
// Only with WS_OVRLAPPED we get a useful default position/size
if ( (nSalFrameStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE)) ==
(SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE) )
nSysStyle |= WS_OVERLAPPED;
else
2002-11-20 16:15:33 +00:00
{
nSysStyle |= WS_POPUP;
if ( !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) )
nExSysStyle |= WS_EX_TOOLWINDOW; // avoid taskbar appearance, for eg splash screen
2002-11-20 16:15:33 +00:00
}
}
if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
{
pFrame->maFrameData.mbCaption = TRUE;
nSysStyle |= WS_SYSMENU | WS_CAPTION;
if ( !hWndParent )
nSysStyle |= WS_SYSMENU | WS_MINIMIZEBOX;
else
nExSysStyle |= WS_EX_DLGMODALFRAME;
if ( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE )
{
pFrame->maFrameData.mbSizeBorder = TRUE;
nSysStyle |= WS_THICKFRAME;
if ( !hWndParent )
nSysStyle |= WS_MAXIMIZEBOX;
}
else
pFrame->maFrameData.mbFixBorder = TRUE;
if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT )
nExSysStyle |= WS_EX_APPWINDOW;
}
if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW
2002-07-11 06:43:29 +00:00
// #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 & SAL_FRAME_STYLE_SIZEABLE) */ )
{
pFrame->maFrameData.mbNoIcon = TRUE;
nExSysStyle |= WS_EX_TOOLWINDOW;
if ( pEnvTransparentFloats && bLayeredAPI == 1 /*&& !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) */)
nExSysStyle |= WS_EX_LAYERED;
}
}
2001-10-24 07:57:18 +00:00
if ( nSalFrameStyle & SAL_FRAME_STYLE_FLOAT )
{
nExSysStyle |= WS_EX_TOOLWINDOW;
pFrame->maFrameData.mbFloatWin = TRUE;
if ( pEnvTransparentFloats && bLayeredAPI == 1 /*&& !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) */)
nExSysStyle |= WS_EX_LAYERED;
2001-10-24 07:57:18 +00:00
}
2000-09-18 16:07:07 +00:00
// init frame data
pFrame->maFrameData.mnStyle = nSalFrameStyle;
// determine show style
pFrame->maFrameData.mnShowState = SW_SHOWNORMAL;
if ( (nSysStyle & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME) )
2000-09-18 16:07:07 +00:00
{
if ( GetSystemMetrics( SM_CXSCREEN ) <= 1024 )
2000-09-18 16:07:07 +00:00
pFrame->maFrameData.mnShowState = SW_SHOWMAXIMIZED;
else
{
if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT )
{
SalData* pSalData = GetSalData();
pFrame->maFrameData.mnShowState = pSalData->mnCmdShow;
if ( (pFrame->maFrameData.mnShowState != SW_SHOWMINIMIZED) &&
(pFrame->maFrameData.mnShowState != SW_MINIMIZE) &&
(pFrame->maFrameData.mnShowState != SW_SHOWMINNOACTIVE) )
{
if ( (pFrame->maFrameData.mnShowState == SW_SHOWMAXIMIZED) ||
(pFrame->maFrameData.mnShowState == SW_MAXIMIZE) )
pFrame->maFrameData.mbOverwriteState = FALSE;
pFrame->maFrameData.mnShowState = SW_SHOWMAXIMIZED;
}
else
pFrame->maFrameData.mbOverwriteState = FALSE;
}
else
{
// Document Windows are also maximized, if the current Document Window
// is also maximized
HWND hWnd = GetForegroundWindow();
if ( hWnd && IsMaximized( hWnd ) &&
(GetWindowInstance( hWnd ) == pInst->maInstData.mhInst) &&
((GetWindowStyle( hWnd ) & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME)) )
pFrame->maFrameData.mnShowState = SW_SHOWMAXIMIZED;
}
}
}
2000-09-18 16:07:07 +00:00
// create frame
if ( aSalShlData.mbWNT )
{
LPCWSTR pClassName;
if ( bSubFrame )
pClassName = SAL_SUBFRAME_CLASSNAMEW;
2000-09-18 16:07:07 +00:00
else
pClassName = SAL_FRAME_CLASSNAMEW;
hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
hWndParent, 0, pInst->maInstData.mhInst, (void*)pFrame );
#ifdef DEBUG
// set transparency value
if( bLayeredAPI == 1 && GetWindowExStyle( hWnd ) & WS_EX_LAYERED )
SetLayeredWindowAttributes( hWnd, 0, 230, LWA_ALPHA );
#endif
2000-09-18 16:07:07 +00:00
}
else
{
LPCSTR pClassName;
if ( bSubFrame )
pClassName = SAL_SUBFRAME_CLASSNAMEA;
2000-09-18 16:07:07 +00:00
else
pClassName = SAL_FRAME_CLASSNAMEA;
hWnd = CreateWindowExA( nExSysStyle, pClassName, "", nSysStyle,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
hWndParent, 0, pInst->maInstData.mhInst, (void*)pFrame );
}
if ( !hWnd )
{
delete pFrame;
return NULL;
}
// If we have an Window with an Caption Bar and without
// an 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 & SAL_FRAME_STYLE_CLOSEABLE) )
2000-09-18 16:07:07 +00:00
{
HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
if ( hSysMenu )
EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
2000-09-18 16:07:07 +00:00
}
// reset input context
pFrame->maFrameData.mhDefIMEContext = ImmAssociateContext( hWnd, 0 );
// determine output size and state
RECT aRect;
GetClientRect( hWnd, &aRect );
pFrame->maFrameData.mnWidth = aRect.right;
pFrame->maFrameData.mnHeight = aRect.bottom;
ImplSaveFrameState( pFrame );
pFrame->maFrameData.mbDefPos = TRUE;
UpdateFrameGeometry( hWnd, pFrame );
2002-01-17 15:11:18 +00:00
2002-02-01 07:41:37 +00:00
if( pFrame->maFrameData.mnShowState == SW_SHOWMAXIMIZED )
2002-01-17 15:11:18 +00:00
{
// #96084 set a useful internal window size because
// the window will not be maximized (and the size updated) before show()
RECT aRect;
2002-11-20 16:15:33 +00:00
ImplSalGetWorkArea( pFrame->maFrameData.mhWnd, &aRect, NULL );
2002-01-17 15:11:18 +00:00
AdjustWindowRectEx( &aRect, GetWindowStyle( hWnd ),
FALSE, GetWindowExStyle( hWnd ) );
pFrame->maGeometry.nX = aRect.left;
pFrame->maGeometry.nY = aRect.top;;
pFrame->maGeometry.nWidth = aRect.right - aRect.left + 1;
pFrame->maGeometry.nHeight = aRect.bottom - aRect.top + 1;
}
2000-09-18 16:07:07 +00:00
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 )
{
HINSTANCE hInstance = GetSalData()->mhInst;
ULONG nSysStyle = GetWindowLong( oldhWnd, GWL_STYLE );
ULONG nExSysStyle = GetWindowLong( oldhWnd, GWL_EXSTYLE );
HWND hWnd = NULL;
if ( aSalShlData.mbWNT )
{
LPCWSTR pClassName = SAL_SUBFRAME_CLASSNAMEW;
hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
hWndParent, 0, hInstance, (void*)GetWindowPtr( oldhWnd ) );
}
else
{
LPCSTR pClassName = SAL_SUBFRAME_CLASSNAMEA;
hWnd = CreateWindowExA( nExSysStyle, pClassName, "", nSysStyle,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
hWndParent, 0, hInstance, (void*)GetWindowPtr( oldhWnd ) );
}
return hWnd;
}
2000-09-18 16:07:07 +00:00
// =======================================================================
// Uebersetzungstabelle von System-Keycodes in StarView-Keycodes
#define KEY_TAB_SIZE 146
static USHORT 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, // 21
0, // 22
0, // 23
0, // 24
0, // 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_COMMA, // VK_SEPARATOR 108
KEY_SUBTRACT, // VK_SUBTRACT 109
KEY_POINT, // 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
};
// =======================================================================
long ImplSalCallbackDummy( void*, SalFrame*, USHORT, const void* )
{
return 0;
}
// -----------------------------------------------------------------------
static UINT ImplSalGetWheelScrollLines()
{
UINT nScrLines = 0;
HWND hWndMsWheel = WIN_FindWindow( MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE );
if ( hWndMsWheel )
{
UINT nGetScrollLinesMsgId = RegisterWindowMessage( MSH_SCROLL_LINES );
nScrLines = (UINT)ImplSendMessage( hWndMsWheel, nGetScrollLinesMsgId, 0, 0 );
}
if ( !nScrLines )
if( !SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &nScrLines, 0 ) )
nScrLines = 0 ;
2000-09-18 16:07:07 +00:00
if ( !nScrLines )
nScrLines = 3;
return nScrLines;
}
// -----------------------------------------------------------------------
static void ImplSalCalcBorder( const SalFrame* pFrame,
int& rLeft, int& rTop, int& rRight, int& rBottom )
{
// set window to screen size
int nFrameX;
int nFrameY;
int nCaptionY;
if ( pFrame->maFrameData.mbSizeBorder )
{
nFrameX = GetSystemMetrics( SM_CXSIZEFRAME );
nFrameY = GetSystemMetrics( SM_CYSIZEFRAME );
}
else if ( pFrame->maFrameData.mbFixBorder )
{
nFrameX = GetSystemMetrics( SM_CXFIXEDFRAME );
nFrameY = GetSystemMetrics( SM_CYFIXEDFRAME );
}
else if ( pFrame->maFrameData.mbBorder )
{
nFrameX = GetSystemMetrics( SM_CXBORDER );
nFrameY = GetSystemMetrics( SM_CYBORDER );
}
else
{
nFrameX = 0;
nFrameY = 0;
}
if ( pFrame->maFrameData.mbCaption )
nCaptionY = GetSystemMetrics( SM_CYCAPTION );
else
nCaptionY = 0;
rLeft = nFrameX;
rTop = nFrameY+nCaptionY;
rRight = nFrameX;
rBottom = nFrameY;
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
static void ImplSalCalcFullScreenSize( const SalFrame* pFrame,
int& rX, int& rY, int& rDX, int& rDY )
{
// set window to screen size
int nFrameX;
int nFrameY;
int nCaptionY;
int nScreenDX;
int nScreenDY;
if ( pFrame->maFrameData.mbSizeBorder )
{
nFrameX = GetSystemMetrics( SM_CXSIZEFRAME );
nFrameY = GetSystemMetrics( SM_CYSIZEFRAME );
}
else if ( pFrame->maFrameData.mbFixBorder )
{
nFrameX = GetSystemMetrics( SM_CXFIXEDFRAME );
nFrameY = GetSystemMetrics( SM_CYFIXEDFRAME );
2000-09-18 16:07:07 +00:00
}
else if ( pFrame->maFrameData.mbBorder )
{
nFrameX = GetSystemMetrics( SM_CXBORDER );
nFrameY = GetSystemMetrics( SM_CYBORDER );
}
else
{
nFrameX = 0;
nFrameY = 0;
}
if ( pFrame->maFrameData.mbCaption )
nCaptionY = GetSystemMetrics( SM_CYCAPTION );
else
nCaptionY = 0;
nScreenDX = GetSystemMetrics( SM_CXSCREEN );
nScreenDY = GetSystemMetrics( SM_CYSCREEN );
rX = -nFrameX;
rY = -(nFrameY+nCaptionY);
rDX = nScreenDX+(nFrameX*2);
rDY = nScreenDY+(nFrameY*2)+nCaptionY;
}
// -----------------------------------------------------------------------
static void ImplSalFrameFullScreenPos( SalFrame* pFrame, BOOL bAlways = FALSE )
{
if ( bAlways || !IsIconic( pFrame->maFrameData.mhWnd ) )
{
// set window to screen size
int nX;
int nY;
int nWidth;
int nHeight;
ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight );
SetWindowPos( pFrame->maFrameData.mhWnd, 0,
nX, nY, nWidth, nHeight,
SWP_NOZORDER | SWP_NOACTIVATE );
}
}
// -----------------------------------------------------------------------
SalFrame::SalFrame()
{
SalData* pSalData = GetSalData();
maFrameData.mhWnd = 0;
maFrameData.mhCursor = LoadCursor( 0, IDC_ARROW );
maFrameData.mhDefIMEContext = 0;
maFrameData.mpGraphics = NULL;
2000-12-14 12:39:14 +00:00
maFrameData.mpGraphics2 = NULL;
2000-09-18 16:07:07 +00:00
maFrameData.mpInst = NULL;
maFrameData.mpProc = ImplSalCallbackDummy;
maFrameData.mnShowState = SW_SHOWNORMAL;
maFrameData.mnWidth = 0;
maFrameData.mnHeight = 0;
maFrameData.mnMinWidth = 0;
maFrameData.mnMinHeight = 0;
2000-09-18 16:07:07 +00:00
maFrameData.mnInputLang = 0;
maFrameData.mnInputCodePage = 0;
maFrameData.mbGraphics = FALSE;
maFrameData.mbCaption = FALSE;
maFrameData.mbBorder = FALSE;
maFrameData.mbFixBorder = FALSE;
2000-09-18 16:07:07 +00:00
maFrameData.mbSizeBorder = FALSE;
maFrameData.mbFullScreen = FALSE;
maFrameData.mbPresentation = FALSE;
maFrameData.mbInShow = FALSE;
maFrameData.mbRestoreMaximize = FALSE;
maFrameData.mbInMoveMsg = FALSE;
maFrameData.mbInSizeMsg = FALSE;
maFrameData.mbFullScreenToolWin = FALSE;
maFrameData.mbDefPos = TRUE;
maFrameData.mbOverwriteState = TRUE;
maFrameData.mbIME = FALSE;
maFrameData.mbHandleIME = FALSE;
maFrameData.mbSpezIME = FALSE;
maFrameData.mbAtCursorIME = FALSE;
maFrameData.mbCandidateMode = FALSE;
2001-10-24 07:57:18 +00:00
maFrameData.mbFloatWin = FALSE;
2001-10-10 06:54:45 +00:00
maFrameData.mbNoIcon = FALSE;
2001-10-24 07:57:18 +00:00
2000-09-18 16:07:07 +00:00
memset( &maFrameData.maState, 0, sizeof( SalFrameState ) );
maFrameData.maSysData.nSize = sizeof( SystemEnvData );
2001-11-23 11:39:27 +00:00
memset( &maGeometry, 0, sizeof( maGeometry ) );
2001-10-24 07:57:18 +00:00
2000-09-18 16:07:07 +00:00
// Daten ermitteln, wenn erster Frame angelegt wird
if ( !pSalData->mpFirstFrame )
{
if ( !aSalShlData.mnWheelMsgId )
aSalShlData.mnWheelMsgId = RegisterWindowMessage( MSH_MOUSEWHEEL );
if ( !aSalShlData.mnWheelScrollLines )
aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
}
// insert frame in framelist
maFrameData.mpNextFrame = pSalData->mpFirstFrame;
pSalData->mpFirstFrame = this;
}
// -----------------------------------------------------------------------
SalFrame::~SalFrame()
{
SalData* pSalData = GetSalData();
2000-12-14 12:39:14 +00:00
// Release Cache DC
if ( maFrameData.mpGraphics2 &&
maFrameData.mpGraphics2->maGraphicsData.mhDC )
ReleaseGraphics( maFrameData.mpGraphics2 );
2000-09-18 16:07:07 +00:00
// destroy saved DC
if ( maFrameData.mpGraphics )
{
if ( maFrameData.mpGraphics->maGraphicsData.mhDefPal )
SelectPalette( maFrameData.mpGraphics->maGraphicsData.mhDC, maFrameData.mpGraphics->maGraphicsData.mhDefPal, TRUE );
ImplSalDeInitGraphics( &(maFrameData.mpGraphics->maGraphicsData) );
ReleaseDC( maFrameData.mhWnd, maFrameData.mpGraphics->maGraphicsData.mhDC );
delete maFrameData.mpGraphics;
}
if ( maFrameData.mhWnd )
{
// reset mouse leave data
if ( pSalData->mhWantLeaveMsg == maFrameData.mhWnd )
{
pSalData->mhWantLeaveMsg = 0;
if ( pSalData->mpMouseLeaveTimer )
{
delete pSalData->mpMouseLeaveTimer;
pSalData->mpMouseLeaveTimer = NULL;
}
}
// destroy system frame
if ( !DestroyWindow( maFrameData.mhWnd ) )
SetWindowPtr( maFrameData.mhWnd, 0 );
}
// remove frame from framelist
if ( this == pSalData->mpFirstFrame )
pSalData->mpFirstFrame = maFrameData.mpNextFrame;
else
{
SalFrame* pTempFrame = pSalData->mpFirstFrame;
while ( pTempFrame->maFrameData.mpNextFrame != this )
pTempFrame = pTempFrame->maFrameData.mpNextFrame;
pTempFrame->maFrameData.mpNextFrame = maFrameData.mpNextFrame;
}
}
// -----------------------------------------------------------------------
SalGraphics* SalFrame::GetGraphics()
{
if ( maFrameData.mbGraphics )
return NULL;
2000-12-14 12:39:14 +00:00
// 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
SalData* pSalData = GetSalData();
if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
2000-09-18 16:07:07 +00:00
{
2000-12-14 12:39:14 +00:00
// We use only three CacheDC's for all threads, because W9x is limited
// to max. 5 Cache DC's per thread
if ( pSalData->mnCacheDCInUse >= 3 )
return NULL;
if ( !maFrameData.mpGraphics2 )
{
2002-07-11 06:43:29 +00:00
maFrameData.mpGraphics2 = new SalGraphicsLayout;
2000-12-14 12:39:14 +00:00
maFrameData.mpGraphics2->maGraphicsData.mhDC = 0;
maFrameData.mpGraphics2->maGraphicsData.mhWnd = maFrameData.mhWnd;
maFrameData.mpGraphics2->maGraphicsData.mbPrinter = FALSE;
maFrameData.mpGraphics2->maGraphicsData.mbVirDev = FALSE;
maFrameData.mpGraphics2->maGraphicsData.mbWindow = TRUE;
maFrameData.mpGraphics2->maGraphicsData.mbScreen = TRUE;
}
HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->maInstData.mhComWnd,
SAL_MSG_GETDC,
(WPARAM)maFrameData.mhWnd, 0 );
2000-09-18 16:07:07 +00:00
if ( hDC )
{
2000-12-14 12:39:14 +00:00
maFrameData.mpGraphics2->maGraphicsData.mhDC = hDC;
2000-09-18 16:07:07 +00:00
if ( pSalData->mhDitherPal )
{
2000-12-14 12:39:14 +00:00
maFrameData.mpGraphics2->maGraphicsData.mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
2000-09-18 16:07:07 +00:00
RealizePalette( hDC );
}
2000-12-14 12:39:14 +00:00
ImplSalInitGraphics( &(maFrameData.mpGraphics2->maGraphicsData) );
2000-09-18 16:07:07 +00:00
maFrameData.mbGraphics = TRUE;
2000-12-14 12:39:14 +00:00
pSalData->mnCacheDCInUse++;
return maFrameData.mpGraphics2;
2000-09-18 16:07:07 +00:00
}
2000-12-14 12:39:14 +00:00
else
return NULL;
2000-09-18 16:07:07 +00:00
}
else
2000-12-14 12:39:14 +00:00
{
if ( !maFrameData.mpGraphics )
{
HDC hDC = GetDC( maFrameData.mhWnd );
if ( hDC )
{
2002-07-11 06:43:29 +00:00
maFrameData.mpGraphics = new SalGraphicsLayout;
2000-12-14 12:39:14 +00:00
maFrameData.mpGraphics->maGraphicsData.mhDC = hDC;
maFrameData.mpGraphics->maGraphicsData.mhWnd = maFrameData.mhWnd;
maFrameData.mpGraphics->maGraphicsData.mbPrinter = FALSE;
maFrameData.mpGraphics->maGraphicsData.mbVirDev = FALSE;
maFrameData.mpGraphics->maGraphicsData.mbWindow = TRUE;
maFrameData.mpGraphics->maGraphicsData.mbScreen = TRUE;
if ( pSalData->mhDitherPal )
{
maFrameData.mpGraphics->maGraphicsData.mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
RealizePalette( hDC );
}
ImplSalInitGraphics( &(maFrameData.mpGraphics->maGraphicsData) );
maFrameData.mbGraphics = TRUE;
}
}
else
maFrameData.mbGraphics = TRUE;
2000-09-18 16:07:07 +00:00
2000-12-14 12:39:14 +00:00
return maFrameData.mpGraphics;
}
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
2000-12-14 12:39:14 +00:00
void SalFrame::ReleaseGraphics( SalGraphics* pGraphics )
2000-09-18 16:07:07 +00:00
{
2000-12-14 12:39:14 +00:00
if ( maFrameData.mpGraphics2 == pGraphics )
{
if ( maFrameData.mpGraphics2->maGraphicsData.mhDC )
{
SalData* pSalData = GetSalData();
if ( maFrameData.mpGraphics2->maGraphicsData.mhDefPal )
SelectPalette( maFrameData.mpGraphics2->maGraphicsData.mhDC, maFrameData.mpGraphics2->maGraphicsData.mhDefPal, TRUE );
ImplSalDeInitGraphics( &(maFrameData.mpGraphics2->maGraphicsData) );
ImplSendMessage( pSalData->mpFirstInstance->maInstData.mhComWnd,
SAL_MSG_RELEASEDC,
(WPARAM)maFrameData.mhWnd,
(LPARAM)maFrameData.mpGraphics2->maGraphicsData.mhDC );
maFrameData.mpGraphics2->maGraphicsData.mhDC = 0;
pSalData->mnCacheDCInUse--;
}
}
2000-09-18 16:07:07 +00:00
maFrameData.mbGraphics = FALSE;
}
// -----------------------------------------------------------------------
BOOL SalFrame::PostEvent( void* pData )
{
return (BOOL)ImplPostMessage( maFrameData.mhWnd, SAL_MSG_USEREVENT, 0, (LPARAM)pData );
}
// -----------------------------------------------------------------------
void SalFrame::SetTitle( const XubString& rTitle )
{
DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "SalFrame::SetTitle(): WCHAR != sal_Unicode" );
if ( !SetWindowTextW( maFrameData.mhWnd, rTitle.GetBuffer() ) )
{
ByteString aAnsiTitle = ImplSalGetWinAnsiString( rTitle );
SetWindowTextA( maFrameData.mhWnd, aAnsiTitle.GetBuffer() );
}
}
// -----------------------------------------------------------------------
void SalFrame::SetIcon( USHORT nIcon )
{
// If we have a window without an Icon (for example a dialog), ignore this call
if ( maFrameData.mbNoIcon )
return;
2001-04-27 13:46:33 +00:00
// 0 means default (class) icon
HICON hIcon = NULL, hSmIcon = NULL;
if ( nIcon )
2001-04-27 13:46:33 +00:00
{
ImplLoadSalIcon( nIcon, hIcon, hSmIcon );
DBG_ASSERT( hIcon , "SalFrame::SetIcon(): Could not load large icon !" );
DBG_ASSERT( hSmIcon , "SalFrame::SetIcon(): Could not load small icon !" );
}
ImplSendMessage( maFrameData.mhWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );
ImplSendMessage( maFrameData.mhWnd, WM_SETICON, ICON_SMALL, (LPARAM)hSmIcon );
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
HWND ImplGetParentHwnd( HWND hWnd )
{
2002-01-10 07:07:19 +00:00
#ifndef REMOTE_APPSERVER
SalFrame* pFrame = GetWindowPtr( hWnd );
if( !pFrame || !pFrame->maFrameData.mpInst)
return ::GetParent( hWnd );
Window *pRealParent = ((Window*)pFrame->maFrameData.mpInst)->mpRealParent;
if( pRealParent )
return pRealParent->mpFrame->maFrameData.mhWnd;
else
return ::GetParent( hWnd );
2002-01-10 07:07:19 +00:00
#else
return ::GetParent( hWnd ); // just to get it compiled for remote case, this function is never executed...
#endif
}
// -----------------------------------------------------------------------
2002-09-18 15:35:23 +00:00
SalFrame* SalFrame::GetParent() const
{
return GetWindowPtr( ImplGetParentHwnd( maFrameData.mhWnd ) );
}
// -----------------------------------------------------------------------
2002-07-16 08:04:37 +00:00
static void ImplSalShow( HWND hWnd, BOOL bVisible, BOOL bNoActivate )
2000-09-18 16:07:07 +00:00
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( !pFrame )
return;
if ( bVisible )
{
pFrame->maFrameData.mbDefPos = FALSE;
pFrame->maFrameData.mbOverwriteState = TRUE;
pFrame->maFrameData.mbInShow = TRUE;
2002-11-20 16:15:33 +00:00
// #i4715, save position
RECT aRectPreMatrox, aRectPostMatrox;
GetWindowRect( hWnd, &aRectPreMatrox );
2002-07-16 08:04:37 +00:00
if( bNoActivate )
ShowWindow( hWnd, SW_SHOWNOACTIVATE );
else
ShowWindow( hWnd, pFrame->maFrameData.mnShowState );
2002-11-20 16:15:33 +00:00
// #i4715, matrox centerpopup might have changed our position
// reposition popups without caption (menues, dropdowns, tooltips)
GetWindowRect( hWnd, &aRectPostMatrox );
if( (GetWindowStyle( hWnd ) & WS_POPUP) &&
!pFrame->maFrameData.mbCaption &&
(aRectPreMatrox.left != aRectPostMatrox.left || aRectPreMatrox.top != aRectPostMatrox.top) )
SetWindowPos( hWnd, 0, aRectPreMatrox.left, aRectPreMatrox.top, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE );
2001-11-23 11:39:27 +00:00
Window *pClientWin = ((Window*)pFrame->maFrameData.mpInst)->ImplGetClientWindow();
if ( pFrame->maFrameData.mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
2001-10-24 07:57:18 +00:00
pFrame->maFrameData.mnShowState = SW_SHOWNOACTIVATE;
else
pFrame->maFrameData.mnShowState = SW_SHOW;
2000-09-18 16:07:07 +00:00
// Damit Taskleiste unter W98 auch gleich ausgeblendet wird
if ( pFrame->maFrameData.mbPresentation )
{
HWND hWndParent = ::GetParent( hWnd );
if ( hWndParent )
SetForegroundWindow( hWndParent );
SetForegroundWindow( hWnd );
}
2001-10-24 07:57:18 +00:00
2000-09-18 16:07:07 +00:00
pFrame->maFrameData.mbInShow = FALSE;
2000-12-14 12:39:14 +00:00
2000-12-14 12:39:14 +00:00
// Direct Paint only, if we get the SolarMutx
if ( ImplSalYieldMutexTryToAcquire() )
{
UpdateWindow( hWnd );
ImplSalYieldMutexRelease();
}
2000-09-18 16:07:07 +00:00
}
else
{
// See also Bug #91813# and #68467#
2000-09-18 16:07:07 +00:00
if ( pFrame->maFrameData.mbFullScreen &&
pFrame->maFrameData.mbPresentation &&
(aSalShlData.mnVersion < 500) &&
2000-09-18 16:07:07 +00:00
!::GetParent( hWnd ) )
{
// Damit im Impress-Player in der Taskleiste nicht durch
// einen Windows-Fehler hin- und wieder mal ein leerer
// Button stehen bleibt, muessen wir hier die Taskleiste
// etwas austricksen. Denn wenn wir im FullScreenMode sind
// und das Fenster hiden kommt Windows anscheinend etwas aus
// dem tritt und somit minimieren wir das Fenster damit es
// nicht flackert
ANIMATIONINFO aInfo;
aInfo.cbSize = sizeof( aInfo );
SystemParametersInfo( SPI_GETANIMATION, 0, &aInfo, 0 );
if ( aInfo.iMinAnimate )
{
int nOldAni = aInfo.iMinAnimate;
aInfo.iMinAnimate = 0;
SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 );
ShowWindow( pFrame->maFrameData.mhWnd, SW_SHOWMINNOACTIVE );
aInfo.iMinAnimate = nOldAni;
SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 );
}
else
ShowWindow( hWnd, SW_SHOWMINNOACTIVE );
ShowWindow( hWnd, SW_HIDE );
}
else
ShowWindow( hWnd, SW_HIDE );
}
}
// -----------------------------------------------------------------------
2002-07-16 08:04:37 +00:00
void SalFrame::Show( BOOL bVisible, BOOL bNoActivate )
2000-09-18 16:07:07 +00:00
{
2000-12-14 12:39:14 +00:00
// 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() )
2002-07-16 08:04:37 +00:00
ImplPostMessage( maFrameData.mhWnd, SAL_MSG_SHOW, bVisible, bNoActivate );
2000-12-14 12:39:14 +00:00
else
2002-07-16 08:04:37 +00:00
ImplSalShow( maFrameData.mhWnd, bVisible, bNoActivate );
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
void SalFrame::Enable( BOOL bEnable )
{
EnableWindow( maFrameData.mhWnd, bEnable );
}
// -----------------------------------------------------------------------
void SalFrame::SetMinClientSize( long nWidth, long nHeight )
{
maFrameData.mnMinWidth = nWidth;
maFrameData.mnMinHeight = nHeight;
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
2001-10-24 07:57:18 +00:00
void SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight,
USHORT nFlags )
2000-09-18 16:07:07 +00:00
{
BOOL bVisible = (GetWindowStyle( maFrameData.mhWnd ) & WS_VISIBLE) != 0;
if ( !bVisible )
2001-10-24 07:57:18 +00:00
{
2001-11-23 11:39:27 +00:00
Window *pClientWin = ((Window*)maFrameData.mpInst)->ImplGetClientWindow();
if ( maFrameData.mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
2001-10-24 07:57:18 +00:00
maFrameData.mnShowState = SW_SHOWNOACTIVATE;
else
maFrameData.mnShowState = SW_SHOWNORMAL;
}
2000-09-18 16:07:07 +00:00
else
{
if ( IsIconic( maFrameData.mhWnd ) || IsZoomed( maFrameData.mhWnd ) )
2001-10-24 07:57:18 +00:00
ShowWindow( maFrameData.mhWnd, SW_RESTORE );
2000-09-18 16:07:07 +00:00
}
2001-10-24 07:57:18 +00:00
USHORT nEvent = 0;
UINT nPosSize = 0;
RECT aClientRect, aWindowRect;
GetClientRect( maFrameData.mhWnd, &aClientRect ); // x,y always 0,0, but width and height without border
GetWindowRect( maFrameData.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
{
//DBG_ASSERT( nX && nY, " 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;
2000-09-18 16:07:07 +00:00
aWinRect.left = 0;
2001-10-24 07:57:18 +00:00
aWinRect.right = (int)nWidth-1;
2000-09-18 16:07:07 +00:00
aWinRect.top = 0;
2001-10-24 07:57:18 +00:00
aWinRect.bottom = (int)nHeight-1;
AdjustWindowRectEx( &aWinRect, GetWindowStyle( maFrameData.mhWnd ),
FALSE, GetWindowExStyle( maFrameData.mhWnd ) );
nWidth = aWinRect.right - aWinRect.left + 1;
nHeight = aWinRect.bottom - aWinRect.top + 1;
2000-09-18 16:07:07 +00:00
2001-10-24 07:57:18 +00:00
if ( ::GetParent( maFrameData.mhWnd ) )
{
2002-07-11 06:43:29 +00:00
// --- RTL --- (mirror window pos)
RECT aParentRect;
GetClientRect( ImplGetParentHwnd( maFrameData.mhWnd ), &aParentRect );
2002-09-18 15:35:23 +00:00
if( Application::GetSettings().GetLayoutRTL() )
2002-07-11 06:43:29 +00:00
nX = (aParentRect.right - aParentRect.left) - nWidth-1 - nX;
2001-10-24 07:57:18 +00:00
POINT aPt;
aPt.x = nX;
aPt.y = nY;
ClientToScreen( ImplGetParentHwnd( maFrameData.mhWnd ), &aPt );
2001-10-24 07:57:18 +00:00
nX = aPt.x;
nY = aPt.y;
}
2000-09-18 16:07:07 +00:00
2001-11-02 17:31:39 +00:00
int nScreenX;
int nScreenY;
int nScreenWidth;
int nScreenHeight;
2002-05-08 10:09:33 +00:00
2001-11-02 17:31:39 +00:00
RECT aRect;
2002-11-20 16:15:33 +00:00
ImplSalGetWorkArea( maFrameData.mhWnd, &aRect, NULL );
2001-11-02 17:31:39 +00:00
nScreenX = aRect.left;
nScreenY = aRect.top;
nScreenWidth = aRect.right-aRect.left;
nScreenHeight = aRect.bottom-aRect.top;
2001-10-24 07:57:18 +00:00
if ( maFrameData.mbDefPos && (nPosSize & SWP_NOMOVE)) // we got no positioning request, so choose default position
2000-09-18 16:07:07 +00:00
{
2001-10-24 07:57:18 +00:00
// center window
HWND hWndParent = ::GetParent( maFrameData.mhWnd );
// Search for TopLevel Frame
while ( hWndParent && (GetWindowStyle( hWndParent ) & WS_CHILD) )
hWndParent = ::GetParent( hWndParent );
// if the Window has a Parent, than center the window to
// the parent, in the other case to the screen
if ( hWndParent && !IsIconic( hWndParent ) &&
(GetWindowStyle( hWndParent ) & WS_VISIBLE) )
{
RECT aParentRect;
GetWindowRect( hWndParent, &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
{
2002-11-20 16:15:33 +00:00
POINT pt;
GetCursorPos( &pt );
RECT aRect;
aRect.left = pt.x;
aRect.top = pt.y;
aRect.right = pt.x+2;
aRect.bottom = pt.y+2;
// dualmonitor support:
// Get screensize of the monitor whith the mouse pointer
ImplSalGetWorkArea( maFrameData.mhWnd, &aRect, &aRect );
nX = ((aRect.right-aRect.left)-nWidth)/2 + aRect.left;
nY = ((aRect.bottom-aRect.top)-nHeight)/2 + aRect.top;
}
2001-10-24 07:57:18 +00:00
//if ( bVisible )
// maFrameData.mbDefPos = FALSE;
maFrameData.mbDefPos = FALSE; // center only once
nPosSize &= ~SWP_NOMOVE; // activate positioning
nEvent = SALEVENT_MOVERESIZE;
2000-09-18 16:07:07 +00:00
}
2001-10-24 07:57:18 +00:00
2001-11-02 17:31:39 +00:00
// Adjust Window in the screen
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( !(maFrameData.mnStyle & SAL_FRAME_STYLE_FLOAT) )
nPosFlags |= SWP_NOZORDER; // do not change z-order
// #102847#, #102978#
// release solar mutex if we're calling the main thread
// and acquire it again afterwards (SetWindowPos switches to the main thread!)
// otherwise the main thread could currently be blocking while it is trying
// to re-acquire the mutex itself
// see toolkit:vclxaccessiblecomponent/WindowEventListener
ULONG nCount = 0;
if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
nCount = Application::ReleaseSolarMutex();
SetWindowPos( maFrameData.mhWnd, HWND_TOP, nX, nY, (int)nWidth, (int)nHeight, nPosFlags );
Application::AcquireSolarMutex( nCount );
UpdateFrameGeometry( maFrameData.mhWnd, this );
2000-09-18 16:07:07 +00:00
2001-10-24 07:57:18 +00:00
// Notification -- really ???
if( nEvent )
maFrameData.mpProc( maFrameData.mpInst, this, nEvent, NULL );
}
// -----------------------------------------------------------------------
void SalFrame::SetParent( SalFrame* pNewParent )
{
mbInReparent = TRUE;
// save hwnd, will be overwritten in WM_CREATE during createwindow
HWND hWndOld = maFrameData.mhWnd;
BOOL bNeedGraphics = maFrameData.mbGraphics;
HFONT hFont = NULL;
HPEN hPen = NULL;
HBRUSH hBrush = NULL;
// Release Cache DC
if ( maFrameData.mpGraphics2 &&
maFrameData.mpGraphics2->maGraphicsData.mhDC )
{
// save current gdi objects before hdc is gone
hFont = (HFONT) GetCurrentObject( maFrameData.mpGraphics2->maGraphicsData.mhDC, OBJ_FONT);
hPen = (HPEN) GetCurrentObject( maFrameData.mpGraphics2->maGraphicsData.mhDC, OBJ_PEN);
hBrush = (HBRUSH) GetCurrentObject( maFrameData.mpGraphics2->maGraphicsData.mhDC, OBJ_BRUSH);
ReleaseGraphics( maFrameData.mpGraphics2 );
}
// destroy saved DC
if ( maFrameData.mpGraphics )
{
if ( maFrameData.mpGraphics->maGraphicsData.mhDefPal )
SelectPalette( maFrameData.mpGraphics->maGraphicsData.mhDC, maFrameData.mpGraphics->maGraphicsData.mhDefPal, TRUE );
ImplSalDeInitGraphics( &(maFrameData.mpGraphics->maGraphicsData) );
ReleaseDC( maFrameData.mhWnd, maFrameData.mpGraphics->maGraphicsData.mhDC );
}
// create a new hwnd with the same styles
HWND hWndParent = pNewParent->maFrameData.mhWnd;
// forward to main thread
HWND hWnd = (HWND) ImplSendMessage( GetSalData()->mpFirstInstance->maInstData.mhComWnd,
SAL_MSG_RECREATEHWND,
(WPARAM) hWndParent, (LPARAM)maFrameData.mhWnd );
// succeeded ?
hWndParent = ::GetParent( hWnd );
DBG_ASSERT( hWndParent == pNewParent->maFrameData.mhWnd, "SalFrame::SetParent not successful");
// make sure we're pointing to the right VCL parent
2002-04-18 14:12:49 +00:00
// FIXME: sclient requires the following statement !!!
//((Window*)maFrameData.mpInst)->mpRealParent = (Window*)pNewParent->maFrameData.mpInst;
// recreate DCs
if( bNeedGraphics )
{
if( maFrameData.mpGraphics2 )
{
// re-create cached DC
HDC hDC = (HDC)ImplSendMessage( GetSalData()->mpFirstInstance->maInstData.mhComWnd,
SAL_MSG_GETDC,
(WPARAM) hWnd, 0 );
if ( hDC )
{
maFrameData.mpGraphics2->maGraphicsData.mhDC = hDC;
if ( GetSalData()->mhDitherPal )
{
maFrameData.mpGraphics2->maGraphicsData.mhDefPal = SelectPalette( hDC, GetSalData()->mhDitherPal, TRUE );
RealizePalette( hDC );
}
ImplSalInitGraphics( &(maFrameData.mpGraphics2->maGraphicsData) );
// re-select saved gdi objects
if( hFont )
SelectObject( hDC, hFont );
if( hPen )
SelectObject( hDC, hPen );
if( hBrush )
SelectObject( hDC, hBrush );
maFrameData.mbGraphics = TRUE;
GetSalData()->mnCacheDCInUse++;
}
}
if( maFrameData.mpGraphics )
{
// re-create DC
maFrameData.mpGraphics->maGraphicsData.mhDC = GetDC( hWnd );
if ( GetSalData()->mhDitherPal )
{
maFrameData.mpGraphics->maGraphicsData.mhDefPal = SelectPalette( maFrameData.mpGraphics->maGraphicsData.mhDC, GetSalData()->mhDitherPal, TRUE );
RealizePalette( maFrameData.mpGraphics->maGraphicsData.mhDC );
}
ImplSalInitGraphics( &(maFrameData.mpGraphics->maGraphicsData) );
maFrameData.mbGraphics = TRUE;
}
}
// now destroy original hwnd
DestroyWindow( hWndOld );
mbInReparent = FALSE;
}
// -----------------------------------------------------------------------
2001-10-24 07:57:18 +00:00
void SalFrame::GetWorkArea( Rectangle &rRect )
{
RECT aRect;
2002-11-20 16:15:33 +00:00
ImplSalGetWorkArea( maFrameData.mhWnd, &aRect, NULL );
2001-10-24 07:57:18 +00:00
rRect.nLeft = aRect.left;
rRect.nRight = aRect.right-1;
rRect.nTop = aRect.top;
rRect.nBottom = aRect.bottom-1;
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
void SalFrame::GetClientSize( long& rWidth, long& rHeight )
{
2002-09-18 15:35:23 +00:00
rWidth = maGeometry.nWidth;
rHeight = maGeometry.nHeight;
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
void SalFrame::SetWindowState( const SalFrameState* pState )
{
// Wir testen, ob das Fenster ueberhaupt auf den Bildschirm passt, damit
// nicht wenn die Bildschirm-Aufloesung geaendert wurde, das Fenster aus
// diesem herausragt
int nX;
int nY;
int nWidth;
int nHeight;
int nScreenX;
int nScreenY;
int nScreenWidth;
int nScreenHeight;
RECT aRect;
2002-11-20 16:15:33 +00:00
ImplSalGetWorkArea( maFrameData.mhWnd, &aRect, NULL );
// #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;
2001-08-23 12:45:29 +00:00
UINT nPosSize = 0;
RECT aWinRect;
GetWindowRect( maFrameData.mhWnd, &aWinRect );
2000-09-18 16:07:07 +00:00
// to be consistent with Unix, the frame state is without(!) decoration
// ->add the decoration
RECT aRect2 = aWinRect;
AdjustWindowRectEx( &aRect2, GetWindowStyle( maFrameData.mhWnd ),
FALSE, GetWindowExStyle( maFrameData.mhWnd ) );
long nTopDeco = abs( aWinRect.top - aRect2.top );
long nLeftDeco = abs( aWinRect.left - aRect2.left );
long nBottomDeco = abs( aWinRect.bottom - aRect2.bottom );
long nRightDeco = abs( aWinRect.right - aRect2.right );
2000-09-18 16:07:07 +00:00
// Fenster-Position/Groesse in den Bildschirm einpassen
2001-08-23 12:45:29 +00:00
if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y)) )
nPosSize |= SWP_NOMOVE;
if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)) )
nPosSize |= SWP_NOSIZE;
if ( pState->mnMask & SAL_FRAMESTATE_MASK_X )
nX = (int)pState->mnX - nLeftDeco;
2001-08-23 12:45:29 +00:00
else
nX = aWinRect.left;
if ( pState->mnMask & SAL_FRAMESTATE_MASK_Y )
nY = (int)pState->mnY - nTopDeco;
2001-08-23 12:45:29 +00:00
else
nY = aWinRect.top;
if ( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH )
nWidth = (int)pState->mnWidth + nLeftDeco + nRightDeco;
2001-08-23 12:45:29 +00:00
else
nWidth = aWinRect.right-aWinRect.left;
if ( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT )
nHeight = (int)pState->mnHeight + nTopDeco + nBottomDeco;
2001-08-23 12:45:29 +00:00
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);
2001-08-23 12:45:29 +00:00
if ( nX+nWidth > nScreenX+nScreenWidth )
nX = (nScreenX+nScreenWidth) - nWidth;
if ( nY+nHeight > nScreenY+nScreenHeight )
nY = (nScreenY+nScreenHeight) - nHeight;
2000-09-18 16:07:07 +00:00
if ( nX < nScreenX )
nX = nScreenX;
if ( nY < nScreenY )
nY = nScreenY;
// Restore-Position setzen
WINDOWPLACEMENT aPlacement;
aPlacement.length = sizeof( aPlacement );
GetWindowPlacement( maFrameData.mhWnd, &aPlacement );
// Status setzen
BOOL bVisible = (GetWindowStyle( maFrameData.mhWnd ) & WS_VISIBLE) != 0;
BOOL bUpdateHiddenFramePos = FALSE;
2000-09-18 16:07:07 +00:00
if ( !bVisible )
{
aPlacement.showCmd = SW_HIDE;
if ( maFrameData.mbOverwriteState )
{
2001-08-23 12:45:29 +00:00
if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
{
if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
maFrameData.mnShowState = SW_SHOWMINIMIZED;
else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
{
2001-08-23 12:45:29 +00:00
maFrameData.mnShowState = SW_SHOWMAXIMIZED;
bUpdateHiddenFramePos = TRUE;
}
2001-08-23 12:45:29 +00:00
else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
maFrameData.mnShowState = SW_SHOWNORMAL;
}
2000-09-18 16:07:07 +00:00
}
}
else
{
2001-08-23 12:45:29 +00:00
if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
2000-09-18 16:07:07 +00:00
{
2001-08-23 12:45:29 +00:00
if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
{
if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
aPlacement.flags |= WPF_RESTORETOMAXIMIZED;
aPlacement.showCmd = SW_SHOWMINIMIZED;
}
else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
aPlacement.showCmd = SW_SHOWMAXIMIZED;
else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
aPlacement.showCmd = SW_RESTORE;
2000-09-18 16:07:07 +00:00
}
}
// Wenn Fenster nicht minimiert/maximiert ist oder nicht optisch
// umgesetzt werden muss, dann SetWindowPos() benutzen, da
// SetWindowPlacement() die TaskBar mit einrechnet
if ( !IsIconic( maFrameData.mhWnd ) && !IsZoomed( maFrameData.mhWnd ) &&
(!bVisible || (aPlacement.showCmd == SW_RESTORE)) )
{
if( bUpdateHiddenFramePos )
{
// #96084 set a useful internal window size because
// the window will not be maximized (and the size updated) before show()
RECT aRect;
2002-11-20 16:15:33 +00:00
ImplSalGetWorkArea( maFrameData.mhWnd, &aRect, NULL );
AdjustWindowRectEx( &aRect, GetWindowStyle( maFrameData.mhWnd ),
FALSE, GetWindowExStyle( maFrameData.mhWnd ) );
maGeometry.nX = aRect.left;
maGeometry.nY = aRect.top;;
maGeometry.nWidth = aRect.right - aRect.left + 1;
maGeometry.nHeight = aRect.bottom - aRect.top + 1;
}
else
SetWindowPos( maFrameData.mhWnd, 0,
2000-09-18 16:07:07 +00:00
nX, nY, nWidth, nHeight,
2001-08-23 12:45:29 +00:00
SWP_NOZORDER | SWP_NOACTIVATE | nPosSize );
2000-09-18 16:07:07 +00:00
}
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;
}
2000-09-18 16:07:07 +00:00
SetWindowPlacement( maFrameData.mhWnd, &aPlacement );
}
if( !(nPosSize & SWP_NOMOVE) )
maFrameData.mbDefPos = FALSE; // window was positioned
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
BOOL SalFrame::GetWindowState( SalFrameState* pState )
{
if ( maFrameData.maState.mnWidth && maFrameData.maState.mnHeight )
{
*pState = maFrameData.maState;
// #94144# allow Minimize again, should be masked out when read from configuration
// 91625 - Don't save minimize
//if ( !(pState->mnState & SAL_FRAMESTATE_MAXIMIZED) )
if ( !(pState->mnState & (SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED)) )
2001-08-23 12:45:29 +00:00
pState->mnState |= SAL_FRAMESTATE_NORMAL;
2000-09-18 16:07:07 +00:00
return TRUE;
}
return FALSE;
}
// -----------------------------------------------------------------------
void SalFrame::ShowFullScreen( BOOL bFullScreen )
{
if ( maFrameData.mbFullScreen == bFullScreen )
return;
maFrameData.mbFullScreen = bFullScreen;
if ( bFullScreen )
{
#if ( WINVER >= 0x0400 )
// Damit Taskleiste von Windows ausgeblendet wird
DWORD nExStyle = GetWindowExStyle( maFrameData.mhWnd );
if ( nExStyle & WS_EX_TOOLWINDOW )
{
maFrameData.mbFullScreenToolWin = TRUE;
nExStyle &= ~WS_EX_TOOLWINDOW;
SetWindowExStyle( maFrameData.mhWnd, nExStyle );
}
#endif
// save old position
GetWindowRect( maFrameData.mhWnd, &maFrameData.maFullScreenRect );
// save show state
maFrameData.mnFullScreenShowState = maFrameData.mnShowState;
if ( !(GetWindowStyle( maFrameData.mhWnd ) & WS_VISIBLE) )
maFrameData.mnShowState = SW_SHOW;
// set window to screen size
ImplSalFrameFullScreenPos( this, TRUE );
}
else
{
// wenn ShowState wieder hergestellt werden muss, hiden wir zuerst
// das Fenster, damit es nicht so sehr flackert
BOOL bVisible = (GetWindowStyle( maFrameData.mhWnd ) & WS_VISIBLE) != 0;
if ( bVisible && (maFrameData.mnShowState != maFrameData.mnFullScreenShowState) )
ShowWindow( maFrameData.mhWnd, SW_HIDE );
#if ( WINVER >= 0x0400 )
if ( maFrameData.mbFullScreenToolWin )
SetWindowExStyle( maFrameData.mhWnd, GetWindowExStyle( maFrameData.mhWnd ) | WS_EX_TOOLWINDOW );
maFrameData.mbFullScreenToolWin = FALSE;
#endif
SetWindowPos( maFrameData.mhWnd, 0,
maFrameData.maFullScreenRect.left,
maFrameData.maFullScreenRect.top,
maFrameData.maFullScreenRect.right-maFrameData.maFullScreenRect.left,
maFrameData.maFullScreenRect.bottom-maFrameData.maFullScreenRect.top,
SWP_NOZORDER | SWP_NOACTIVATE );
// restore show state
if ( maFrameData.mnShowState != maFrameData.mnFullScreenShowState )
{
maFrameData.mnShowState = maFrameData.mnFullScreenShowState;
if ( bVisible )
{
maFrameData.mbInShow = TRUE;
ShowWindow( maFrameData.mhWnd, maFrameData.mnShowState );
maFrameData.mbInShow = FALSE;
UpdateWindow( maFrameData.mhWnd );
}
}
}
}
// -----------------------------------------------------------------------
void SalFrame::StartPresentation( BOOL bStart )
{
if ( maFrameData.mbPresentation == bStart )
return;
maFrameData.mbPresentation = bStart;
SalData* pSalData = GetSalData();
if ( bStart )
{
#if ( WINVER >= 0x0400 )
if ( !pSalData->mpSageEnableProc )
{
if ( pSalData->mnSageStatus != DISABLE_AGENT )
{
OFSTRUCT aOS;
OpenFile( "SAGE.DLL", &aOS, OF_EXIST );
if ( !aOS.nErrCode )
{
pSalData->mhSageInst = LoadLibrary( aOS.szPathName );
pSalData->mpSageEnableProc = (SysAgt_Enable_PROC)GetProcAddress( pSalData->mhSageInst, "System_Agent_Enable" );
}
else
pSalData->mnSageStatus = DISABLE_AGENT;
}
}
if ( pSalData->mpSageEnableProc )
{
pSalData->mnSageStatus = pSalData->mpSageEnableProc( GET_AGENT_STATUS );
if ( pSalData->mnSageStatus == ENABLE_AGENT )
pSalData->mpSageEnableProc( DISABLE_AGENT );
}
#endif
// Bildschirmschoner ausschalten, wenn Praesentation laueft
SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0,
&(pSalData->mbScrSvrEnabled), 0 );
if ( pSalData->mbScrSvrEnabled )
SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, FALSE, 0, 0 );
}
else
{
// Bildschirmschoner wieder einschalten
if ( pSalData->mbScrSvrEnabled )
SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, pSalData->mbScrSvrEnabled, 0, 0 );
#if ( WINVER >= 0x0400 )
// Systemagenten wieder aktivieren
if ( pSalData->mnSageStatus == ENABLE_AGENT )
pSalData->mpSageEnableProc( pSalData->mnSageStatus );
#endif
}
}
// -----------------------------------------------------------------------
void SalFrame::SetAlwaysOnTop( BOOL bOnTop )
{
HWND hWnd;
if ( bOnTop )
hWnd = HWND_TOPMOST;
else
hWnd = HWND_NOTOPMOST;
SetWindowPos( maFrameData.mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
}
// -----------------------------------------------------------------------
static void ImplSalToTop( HWND hWnd, USHORT nFlags )
{
if ( nFlags & SAL_FRAME_TOTOP_FOREGROUNDTASK )
SetForegroundWindow( hWnd );
if ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
{
HWND hIconicWnd = hWnd;
while ( hIconicWnd )
{
if ( IsIconic( hIconicWnd ) )
{
SalFrame* pFrame = GetWindowPtr( hIconicWnd );
if ( pFrame )
{
if ( GetWindowPtr( hWnd )->maFrameData.mbRestoreMaximize )
ShowWindow( hIconicWnd, SW_MAXIMIZE );
else
ShowWindow( hIconicWnd, SW_RESTORE );
}
else
ShowWindow( hIconicWnd, SW_RESTORE );
}
hIconicWnd = ::GetParent( hIconicWnd );
}
}
2000-09-18 16:07:07 +00:00
if ( !IsIconic( hWnd ) )
{
SetFocus( hWnd );
// Windows behauptet oefters mal, das man den Focus hat, obwohl
// man diesen nicht hat. Wenn dies der Fall ist, dann versuchen
// wir diesen auch ganz richtig zu bekommen.
if ( ::GetFocus() == hWnd )
SetForegroundWindow( hWnd );
}
}
// -----------------------------------------------------------------------
void SalFrame::ToTop( USHORT nFlags )
{
2002-04-15 11:50:03 +00:00
nFlags &= ~SAL_FRAME_TOTOP_GRABFOCUS; // this flag is not needed on win32
2000-12-14 12:39:14 +00:00
// 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() )
ImplPostMessage( maFrameData.mhWnd, SAL_MSG_TOTOP, nFlags, 0 );
else
ImplSalToTop( maFrameData.mhWnd, nFlags );
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
void SalFrame::SetPointer( PointerStyle ePointerStyle )
{
struct ImplPtrData
{
HCURSOR mhCursor;
LPCSTR mnSysId;
UINT mnOwnId;
};
static ImplPtrData aImplPtrTab[POINTER_COUNT] =
{
{ 0, IDC_ARROW, 0 }, // POINTER_ARROW
{ 0, 0, SAL_RESID_POINTER_NULL }, // POINTER_NULL
{ 0, IDC_WAIT, 0 }, // POINTER_WAIT
{ 0, IDC_IBEAM, 0 }, // POINTER_TEXT
#if ( WINVER >= 0x0400 )
{ 0, IDC_HELP, 0 }, // POINTER_HELP
#else
{ 0, 0, SAL_RESID_POINTER_HELP }, // POINTER_HELP
#endif
{ 0, 0, SAL_RESID_POINTER_CROSS }, // POINTER_CROSS
{ 0, 0, SAL_RESID_POINTER_MOVE }, // POINTER_MOVE
{ 0, IDC_SIZENS, 0 }, // POINTER_NSIZE
{ 0, IDC_SIZENS, 0 }, // POINTER_SSIZE
{ 0, IDC_SIZEWE, 0 }, // POINTER_WSIZE
{ 0, IDC_SIZEWE, 0 }, // POINTER_ESIZE
{ 0, IDC_SIZENWSE, 0 }, // POINTER_NWSIZE
{ 0, IDC_SIZENESW, 0 }, // POINTER_NESIZE
{ 0, IDC_SIZENESW, 0 }, // POINTER_SWSIZE
{ 0, IDC_SIZENWSE, 0 }, // POINTER_SESIZE
{ 0, IDC_SIZENS, 0 }, // POINTER_WINDOW_NSIZE
{ 0, IDC_SIZENS, 0 }, // POINTER_WINDOW_SSIZE
{ 0, IDC_SIZEWE, 0 }, // POINTER_WINDOW_WSIZE
{ 0, IDC_SIZEWE, 0 }, // POINTER_WINDOW_ESIZE
{ 0, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_NWSIZE
{ 0, IDC_SIZENESW, 0 }, // POINTER_WINDOW_NESIZE
{ 0, IDC_SIZENESW, 0 }, // POINTER_WINDOW_SWSIZE
{ 0, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_SESIZE
{ 0, 0, SAL_RESID_POINTER_HSPLIT }, // POINTER_HSPLIT
{ 0, 0, SAL_RESID_POINTER_VSPLIT }, // POINTER_VSPLIT
{ 0, 0, SAL_RESID_POINTER_HSIZEBAR }, // POINTER_HSIZEBAR
{ 0, 0, SAL_RESID_POINTER_VSIZEBAR }, // POINTER_VSIZEBAR
{ 0, 0, SAL_RESID_POINTER_HAND }, // POINTER_HAND
{ 0, 0, SAL_RESID_POINTER_REFHAND }, // POINTER_REFHAND
{ 0, 0, SAL_RESID_POINTER_PEN }, // POINTER_PEN
{ 0, 0, SAL_RESID_POINTER_MAGNIFY }, // POINTER_MAGNIFY
{ 0, 0, SAL_RESID_POINTER_FILL }, // POINTER_FILL
{ 0, 0, SAL_RESID_POINTER_ROTATE }, // POINTER_ROTATE
{ 0, 0, SAL_RESID_POINTER_HSHEAR }, // POINTER_HSHEAR
{ 0, 0, SAL_RESID_POINTER_VSHEAR }, // POINTER_VSHEAR
{ 0, 0, SAL_RESID_POINTER_MIRROR }, // POINTER_MIRROR
{ 0, 0, SAL_RESID_POINTER_CROOK }, // POINTER_CROOK
{ 0, 0, SAL_RESID_POINTER_CROP }, // POINTER_CROP
{ 0, 0, SAL_RESID_POINTER_MOVEPOINT }, // POINTER_MOVEPOINT
{ 0, 0, SAL_RESID_POINTER_MOVEBEZIERWEIGHT }, // POINTER_MOVEBEZIERWEIGHT
{ 0, 0, SAL_RESID_POINTER_MOVEDATA }, // POINTER_MOVEDATA
{ 0, 0, SAL_RESID_POINTER_COPYDATA }, // POINTER_COPYDATA
{ 0, 0, SAL_RESID_POINTER_LINKDATA }, // POINTER_LINKDATA
{ 0, 0, SAL_RESID_POINTER_MOVEDATALINK }, // POINTER_MOVEDATALINK
{ 0, 0, SAL_RESID_POINTER_COPYDATALINK }, // POINTER_COPYDATALINK
{ 0, 0, SAL_RESID_POINTER_MOVEFILE }, // POINTER_MOVEFILE
{ 0, 0, SAL_RESID_POINTER_COPYFILE }, // POINTER_COPYFILE
{ 0, 0, SAL_RESID_POINTER_LINKFILE }, // POINTER_LINKFILE
{ 0, 0, SAL_RESID_POINTER_MOVEFILELINK }, // POINTER_MOVEFILELINK
{ 0, 0, SAL_RESID_POINTER_COPYFILELINK }, // POINTER_COPYFILELINK
{ 0, 0, SAL_RESID_POINTER_MOVEFILES }, // POINTER_MOVEFILES
{ 0, 0, SAL_RESID_POINTER_COPYFILES }, // POINTER_COPYFILES
{ 0, 0, SAL_RESID_POINTER_NOTALLOWED }, // POINTER_NOTALLOWED
{ 0, 0, SAL_RESID_POINTER_DRAW_LINE }, // POINTER_DRAW_LINE
{ 0, 0, SAL_RESID_POINTER_DRAW_RECT }, // POINTER_DRAW_RECT
{ 0, 0, SAL_RESID_POINTER_DRAW_POLYGON }, // POINTER_DRAW_POLYGON
{ 0, 0, SAL_RESID_POINTER_DRAW_BEZIER }, // POINTER_DRAW_BEZIER
{ 0, 0, SAL_RESID_POINTER_DRAW_ARC }, // POINTER_DRAW_ARC
{ 0, 0, SAL_RESID_POINTER_DRAW_PIE }, // POINTER_DRAW_PIE
{ 0, 0, SAL_RESID_POINTER_DRAW_CIRCLECUT }, // POINTER_DRAW_CIRCLECUT
{ 0, 0, SAL_RESID_POINTER_DRAW_ELLIPSE }, // POINTER_DRAW_ELLIPSE
{ 0, 0, SAL_RESID_POINTER_DRAW_FREEHAND }, // POINTER_DRAW_FREEHAND
{ 0, 0, SAL_RESID_POINTER_DRAW_CONNECT }, // POINTER_DRAW_CONNECT
{ 0, 0, SAL_RESID_POINTER_DRAW_TEXT }, // POINTER_DRAW_TEXT
{ 0, 0, SAL_RESID_POINTER_DRAW_CAPTION }, // POINTER_DRAW_CAPTION
{ 0, 0, SAL_RESID_POINTER_CHART }, // POINTER_CHART
{ 0, 0, SAL_RESID_POINTER_DETECTIVE }, // POINTER_DETECTIVE
{ 0, 0, SAL_RESID_POINTER_PIVOT_COL }, // POINTER_PIVOT_COL
{ 0, 0, SAL_RESID_POINTER_PIVOT_ROW }, // POINTER_PIVOT_ROW
{ 0, 0, SAL_RESID_POINTER_PIVOT_FIELD }, // POINTER_PIVOT_FIELD
{ 0, 0, SAL_RESID_POINTER_CHAIN }, // POINTER_CHAIN
{ 0, 0, SAL_RESID_POINTER_CHAIN_NOTALLOWED }, // POINTER_CHAIN_NOTALLOWED
{ 0, 0, SAL_RESID_POINTER_TIMEEVENT_MOVE }, // POINTER_TIMEEVENT_MOVE
{ 0, 0, SAL_RESID_POINTER_TIMEEVENT_SIZE }, // POINTER_TIMEEVENT_SIZE
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_N }, // POINTER_AUTOSCROLL_N
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_S }, // POINTER_AUTOSCROLL_S
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_W }, // POINTER_AUTOSCROLL_W
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_E }, // POINTER_AUTOSCROLL_E
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NW }, // POINTER_AUTOSCROLL_NW
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NE }, // POINTER_AUTOSCROLL_NE
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SW }, // POINTER_AUTOSCROLL_SW
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SE }, // POINTER_AUTOSCROLL_SE
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NS }, // POINTER_AUTOSCROLL_NS
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_WE }, // POINTER_AUTOSCROLL_WE
{ 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NSWE }, // POINTER_AUTOSCROLL_NSWE
2000-11-15 19:52:59 +00:00
{ 0, 0, SAL_RESID_POINTER_AIRBRUSH }, // POINTER_AIRBRUSH
{ 0, 0, SAL_RESID_POINTER_TEXT_VERTICAL }, // POINTER_TEXT_VERTICAL
{ 0, 0, SAL_RESID_POINTER_PIVOT_DELETE } // POINTER_PIVOT_DELETE
2000-09-18 16:07:07 +00:00
};
2002-10-08 12:24:49 +00:00
#if POINTER_COUNT != 88
2000-09-18 16:07:07 +00:00
#error New Pointer must be defined!
#endif
// Mousepointer loaded ?
if ( !aImplPtrTab[ePointerStyle].mhCursor )
{
if ( aImplPtrTab[ePointerStyle].mnOwnId )
aImplPtrTab[ePointerStyle].mhCursor = ImplLoadSalCursor( aImplPtrTab[ePointerStyle].mnOwnId );
else
aImplPtrTab[ePointerStyle].mhCursor = LoadCursor( 0, aImplPtrTab[ePointerStyle].mnSysId );
}
// Unterscheidet sich der Mauspointer, dann den neuen setzen
if ( maFrameData.mhCursor != aImplPtrTab[ePointerStyle].mhCursor )
{
maFrameData.mhCursor = aImplPtrTab[ePointerStyle].mhCursor;
SetCursor( maFrameData.mhCursor );
}
}
// -----------------------------------------------------------------------
void SalFrame::CaptureMouse( BOOL bCapture )
{
// Send this Message to the window, because CaptureMouse() only work
// in the thread of the window, which has create this window
int nMsg;
if ( bCapture )
nMsg = SAL_MSG_CAPTUREMOUSE;
else
nMsg = SAL_MSG_RELEASEMOUSE;
ImplSendMessage( maFrameData.mhWnd, nMsg, 0, 0 );
}
// -----------------------------------------------------------------------
void SalFrame::SetPointerPos( long nX, long nY )
{
POINT aPt;
aPt.x = (int)nX;
aPt.y = (int)nY;
ClientToScreen( maFrameData.mhWnd, &aPt );
SetCursorPos( aPt.x, aPt.y );
}
// -----------------------------------------------------------------------
void SalFrame::Flush()
{
GdiFlush();
}
// -----------------------------------------------------------------------
void SalFrame::Sync()
{
GdiFlush();
}
// -----------------------------------------------------------------------
2001-06-22 13:15:50 +00:00
static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pContext )
2000-09-18 16:07:07 +00:00
{
2001-06-22 13:15:50 +00:00
SalFrame* pFrame = GetWindowPtr( hWnd );
BOOL bIME = (pContext->mnOptions & SAL_INPUTCONTEXT_TEXT) != 0;
2000-11-03 13:17:43 +00:00
if ( bIME )
2000-09-18 16:07:07 +00:00
{
2001-06-22 13:15:50 +00:00
if ( !pFrame->maFrameData.mbIME )
2000-11-03 13:17:43 +00:00
{
2001-06-22 13:15:50 +00:00
pFrame->maFrameData.mbIME = TRUE;
2000-11-03 13:17:43 +00:00
2001-06-22 13:15:50 +00:00
if ( pFrame->maFrameData.mhDefIMEContext )
2000-11-03 13:17:43 +00:00
{
2001-06-22 13:15:50 +00:00
ImmAssociateContext( pFrame->maFrameData.mhWnd, pFrame->maFrameData.mhDefIMEContext );
2000-11-03 13:17:43 +00:00
UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
2001-06-22 13:15:50 +00:00
pFrame->maFrameData.mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
pFrame->maFrameData.mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
pFrame->maFrameData.mbHandleIME = !pFrame->maFrameData.mbSpezIME;
2000-11-03 13:17:43 +00:00
}
}
// When the application can't handle IME messages, then the
// System should handle the IME handling
if ( !(pContext->mnOptions & SAL_INPUTCONTEXT_EXTTEXTINPUT) )
2001-06-22 13:15:50 +00:00
pFrame->maFrameData.mbHandleIME = FALSE;
2000-11-03 13:17:43 +00:00
// Set the Font for IME Handling
if ( pContext->mpFont )
{
2001-06-22 13:15:50 +00:00
HIMC hIMC = ImmGetContext( pFrame->maFrameData.mhWnd );
2000-11-03 13:17:43 +00:00
if ( hIMC )
{
LOGFONTW aLogFont;
2001-06-22 13:15:50 +00:00
HDC hDC = GetDC( pFrame->maFrameData.mhWnd );
// In case of vertical writing, always append a '@' to the
// Windows font name, not only if such a Windows font really is
// available (bTestVerticalAvail == false in the below call):
// The Windows IME's candidates window seems to always use a
// font that has all necessary glyphs, not necessarily the one
// specified by this font name; but it seems to decide whether
// to use that font's horizontal or vertical variant based on a
// '@' in front of this font name.
ImplGetLogFontFromFontSelect( hDC, pContext->mpFont, aLogFont,
false );
2001-06-22 13:15:50 +00:00
ReleaseDC( pFrame->maFrameData.mhWnd, hDC );
2000-11-03 13:17:43 +00:00
ImmSetCompositionFontW( hIMC, &aLogFont );
2001-06-22 13:15:50 +00:00
ImmReleaseContext( pFrame->maFrameData.mhWnd, hIMC );
2000-11-03 13:17:43 +00:00
}
}
2000-09-18 16:07:07 +00:00
}
else
{
2001-06-22 13:15:50 +00:00
if ( pFrame->maFrameData.mbIME )
2000-09-18 16:07:07 +00:00
{
2001-06-22 13:15:50 +00:00
pFrame->maFrameData.mbIME = FALSE;
pFrame->maFrameData.mbHandleIME = FALSE;
ImmAssociateContext( pFrame->maFrameData.mhWnd, 0 );
2000-09-18 16:07:07 +00:00
}
}
}
// -----------------------------------------------------------------------
2001-06-22 13:15:50 +00:00
void SalFrame::SetInputContext( SalInputContext* pContext )
{
// Must be called in the main thread!
ImplSendMessage( maFrameData.mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, (LPARAM)(void*)pContext );
}
// -----------------------------------------------------------------------
static void ImplSalFrameEndExtTextInput( HWND hWnd, USHORT nFlags )
2000-09-18 16:07:07 +00:00
{
HIMC hIMC = ImmGetContext( hWnd );
if ( hIMC )
{
DWORD nIndex;
if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE )
nIndex = CPS_COMPLETE;
else
nIndex = CPS_CANCEL;
ImmNotifyIME( hIMC, NI_COMPOSITIONSTR, nIndex, 0 );
ImmReleaseContext( hWnd, hIMC );
}
}
// -----------------------------------------------------------------------
2001-06-22 13:15:50 +00:00
void SalFrame::EndExtTextInput( USHORT nFlags )
{
// Must be called in the main thread!
ImplSendMessage( maFrameData.mhWnd, SAL_MSG_ENDEXTTEXTINPUT, (WPARAM)nFlags, 0 );
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
static void ImplGetKeyNameText( LONG lParam, sal_Unicode* pBuf,
UINT& rCount, UINT nMaxSize,
const sal_Char* pReplace )
{
DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "SalFrame::ImplGetKeyNameTextW(): WCHAR != sal_Unicode" );
WCHAR aKeyBuf[350];
int nKeyLen = 0;
if ( lParam )
{
nKeyLen = GetKeyNameTextW( lParam, aKeyBuf, sizeof( aKeyBuf ) / sizeof( sal_Unicode ) );
if ( nKeyLen > 0 )
{
// Convert name, so that the keyname start with an upper
// char and the rest of the word are in lower chars
CharLowerBuffW( aKeyBuf, nKeyLen );
CharUpperBuffW( aKeyBuf, 1 );
WCHAR cTempChar;
WCHAR* pKeyBuf = aKeyBuf;
while ( (cTempChar = *pKeyBuf) != 0 )
{
if ( (cTempChar == '+') || (cTempChar == '-') ||
(cTempChar == ' ') || (cTempChar == '.') )
CharUpperBuffW( pKeyBuf+1, 1 );
pKeyBuf++;
}
}
else
{
sal_Char aAnsiKeyBuf[250];
int nAnsiKeyLen = GetKeyNameTextA( lParam, aAnsiKeyBuf, sizeof( aAnsiKeyBuf ) / sizeof( sal_Char ) );
if ( nAnsiKeyLen )
{
// Convert name, so that the keyname start with an upper
// char and the rest of the word are in lower chars
CharLowerBuffA( aAnsiKeyBuf, nAnsiKeyLen );
CharUpperBuffA( aAnsiKeyBuf, 1 );
sal_Char cTempChar;
sal_Char* pAnsiKeyBuf = aAnsiKeyBuf;
while ( (cTempChar = *pAnsiKeyBuf) != 0 )
{
if ( (cTempChar == '+') || (cTempChar == '-') ||
(cTempChar == ' ') || (cTempChar == '.') )
CharUpperBuffA( pAnsiKeyBuf+1, 1 );
pAnsiKeyBuf++;
}
// Convert to Unicode and copy the data in the Unicode Buffer
nKeyLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, aAnsiKeyBuf, nAnsiKeyLen, aKeyBuf, sizeof( aKeyBuf ) / sizeof( sal_Unicode ) );
}
}
}
if ( (nKeyLen > 0) || pReplace )
{
if ( rCount )
{
pBuf[rCount] = '+';
rCount++;
}
if ( nKeyLen )
{
memcpy( pBuf+rCount, aKeyBuf, nKeyLen*sizeof( sal_Unicode ) );
rCount += nKeyLen;
}
else
{
while ( *pReplace )
{
pBuf[rCount] = *pReplace;
rCount++;
pReplace++;
}
}
}
else
rCount = 0;
}
// -----------------------------------------------------------------------
XubString SalFrame::GetKeyName( USHORT nKeyCode )
{
XubString aKeyCode;
sal_Unicode aKeyBuf[350];
UINT nKeyBufLen = 0;
UINT nSysCode;
if ( nKeyCode & KEY_MOD2 )
{
nSysCode = MapVirtualKey( VK_MENU, 0 );
nSysCode = (nSysCode << 16) | (((ULONG)1) << 25);
ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen,
sizeof( aKeyBuf ) / sizeof( sal_Unicode ),
"Alt" );
}
if ( nKeyCode & KEY_MOD1 )
{
nSysCode = MapVirtualKey( VK_CONTROL, 0 );
nSysCode = (nSysCode << 16) | (((ULONG)1) << 25);
ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen,
sizeof( aKeyBuf ) / sizeof( sal_Unicode ),
"Ctrl" );
}
if ( nKeyCode & KEY_SHIFT )
{
nSysCode = MapVirtualKey( VK_SHIFT, 0 );
nSysCode = (nSysCode << 16) | (((ULONG)1) << 25);
ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen,
sizeof( aKeyBuf ) / sizeof( sal_Unicode ),
"Shift" );
}
USHORT nCode = nKeyCode & 0x0FFF;
ULONG nSysCode2 = 0;
sal_Char* pReplace = NULL;
sal_Unicode cSVCode = 0;
sal_Char aFBuf[4];
nSysCode = 0;
if ( (nCode >= KEY_0) && (nCode <= KEY_9) )
cSVCode = '0' + (nCode - KEY_0);
else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) )
cSVCode = 'A' + (nCode - KEY_A);
else if ( (nCode >= KEY_F1) && (nCode <= KEY_F26) )
{
nSysCode = VK_F1 + (nCode - KEY_F1);
aFBuf[0] = 'F';
if ( (nCode >= KEY_F1) && (nCode <= KEY_F9) )
{
aFBuf[1] = '1' + (nCode - KEY_F1);
aFBuf[2] = 0;
}
else if ( (nCode >= KEY_F10) && (nCode <= KEY_F19) )
{
aFBuf[1] = '1';
aFBuf[2] = '0' + (nCode - KEY_F10);
aFBuf[3] = 0;
}
else
{
aFBuf[1] = '2';
aFBuf[2] = '0' + (nCode - KEY_F20);
aFBuf[3] = 0;
}
pReplace = aFBuf;
}
else
{
switch ( nCode )
{
case KEY_DOWN:
nSysCode = VK_DOWN;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Down";
break;
case KEY_UP:
nSysCode = VK_UP;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Up";
break;
case KEY_LEFT:
nSysCode = VK_LEFT;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Left";
break;
case KEY_RIGHT:
nSysCode = VK_RIGHT;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Right";
break;
case KEY_HOME:
nSysCode = VK_HOME;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Home";
break;
case KEY_END:
nSysCode = VK_END;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "End";
break;
case KEY_PAGEUP:
nSysCode = VK_PRIOR;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Page Up";
break;
case KEY_PAGEDOWN:
nSysCode = VK_NEXT;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Page Down";
break;
case KEY_RETURN:
nSysCode = VK_RETURN;
pReplace = "Enter";
break;
case KEY_ESCAPE:
nSysCode = VK_ESCAPE;
pReplace = "Escape";
break;
case KEY_TAB:
nSysCode = VK_TAB;
pReplace = "Tab";
break;
case KEY_BACKSPACE:
nSysCode = VK_BACK;
pReplace = "Backspace";
break;
case KEY_SPACE:
nSysCode = VK_SPACE;
pReplace = "Space";
break;
case KEY_INSERT:
nSysCode = VK_INSERT;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Insert";
break;
case KEY_DELETE:
nSysCode = VK_DELETE;
nSysCode2 = (((ULONG)1) << 24);
pReplace = "Delete";
break;
case KEY_ADD:
cSVCode = '+';
break;
case KEY_SUBTRACT:
cSVCode = '-';
break;
case KEY_MULTIPLY:
cSVCode = '*';
break;
case KEY_DIVIDE:
cSVCode = '/';
break;
case KEY_POINT:
cSVCode = '.';
break;
case KEY_COMMA:
cSVCode = ',';
break;
case KEY_LESS:
cSVCode = '<';
break;
case KEY_GREATER:
cSVCode = '>';
break;
case KEY_EQUAL:
cSVCode = '=';
break;
}
}
if ( nSysCode )
{
nSysCode = MapVirtualKey( (UINT)nSysCode, 0 );
if ( nSysCode )
nSysCode = (nSysCode << 16) | nSysCode2;
ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen,
sizeof( aKeyBuf ) / sizeof( sal_Unicode ),
pReplace );
}
else
{
if ( cSVCode )
{
if ( !nKeyBufLen )
{
aKeyBuf[0] = cSVCode;
nKeyBufLen = 1;
}
else
{
aKeyBuf[nKeyBufLen] = '+';
nKeyBufLen++;
aKeyBuf[nKeyBufLen] = cSVCode;
nKeyBufLen++;
}
}
}
if ( nKeyBufLen )
aKeyCode.Assign( (const sal_Unicode*)aKeyBuf, nKeyBufLen );
return aKeyCode;
}
// -----------------------------------------------------------------------
XubString SalFrame::GetSymbolKeyName( const XubString&, USHORT nKeyCode )
{
return GetKeyName( nKeyCode );
}
// -----------------------------------------------------------------------
inline Color ImplWinColorToSal( COLORREF nColor )
{
return Color( GetRValue( nColor ), GetGValue( nColor ), GetBValue( nColor ) );
}
// -----------------------------------------------------------------------
2001-06-07 15:52:11 +00:00
static void ImplSalUpdateStyleFontA( HDC hDC, const LOGFONTA& rLogFont, Font& rFont,
BOOL bReplaceFont )
2000-09-18 16:07:07 +00:00
{
2001-06-07 15:52:11 +00:00
ImplSalLogFontToFontA( hDC, rLogFont, rFont, bReplaceFont );
// On Windows 9x, Windows NT we get sometimes very small sizes
// (for example for the small Caption height).
// So if it is MS Sans Serif, a none scalable font we use
// 8 Point as the minimum control height, in all other cases
// 6 Point is the smallest one
if ( rFont.GetHeight() < 8 )
{
if ( rtl_str_compareIgnoreAsciiCase( rLogFont.lfFaceName, "MS Sans Serif" ) == 0 )
rFont.SetHeight( 8 );
else if ( rFont.GetHeight() < 6 )
rFont.SetHeight( 6 );
}
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
2001-06-07 15:52:11 +00:00
static void ImplSalUpdateStyleFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont,
BOOL bReplaceFont )
2000-09-18 16:07:07 +00:00
{
2001-06-07 15:52:11 +00:00
ImplSalLogFontToFontW( hDC, rLogFont, rFont, bReplaceFont );
// On Windows 9x, Windows NT we get sometimes very small sizes
// (for example for the small Caption height).
// So if it is MS Sans Serif, a none scalable font we use
// 8 Point as the minimum control height, in all other cases
// 6 Point is the smallest one
if ( rFont.GetHeight() < 8 )
{
if ( rtl_ustr_compareIgnoreAsciiCase( rLogFont.lfFaceName, L"MS Sans Serif" ) == 0 )
rFont.SetHeight( 8 );
else if ( rFont.GetHeight() < 6 )
rFont.SetHeight( 6 );
}
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
static long ImplA2I( const BYTE* pStr )
{
long n = 0;
int nSign = 1;
if ( *pStr == '-' )
{
nSign = -1;
pStr++;
}
while( (*pStr >= 48) && (*pStr <= 57) )
{
n *= 10;
n += ((*pStr) - 48);
pStr++;
}
n *= nSign;
return n;
}
// -----------------------------------------------------------------------
void SalFrame::UpdateSettings( AllSettings& rSettings )
{
MouseSettings aMouseSettings = rSettings.GetMouseSettings();
aMouseSettings.SetDoubleClickTime( GetDoubleClickTime() );
aMouseSettings.SetDoubleClickWidth( GetSystemMetrics( SM_CXDOUBLECLK ) );
aMouseSettings.SetDoubleClickHeight( GetSystemMetrics( SM_CYDOUBLECLK ) );
long nDragWidth = GetSystemMetrics( SM_CXDRAG );
long nDragHeight = GetSystemMetrics( SM_CYDRAG );
if ( nDragWidth )
aMouseSettings.SetStartDragWidth( nDragWidth );
if ( nDragHeight )
aMouseSettings.SetStartDragHeight( nDragHeight );
HKEY hRegKey;
if ( RegOpenKey( HKEY_CURRENT_USER,
"Control Panel\\Desktop",
&hRegKey ) == ERROR_SUCCESS )
{
BYTE aValueBuf[10];
DWORD nValueSize = sizeof( aValueBuf );
DWORD nType;
if ( RegQueryValueEx( hRegKey, "MenuShowDelay", 0,
&nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
{
if ( nType == REG_SZ )
aMouseSettings.SetMenuDelay( (ULONG)ImplA2I( aValueBuf ) );
}
RegCloseKey( hRegKey );
}
StyleSettings aStyleSettings = rSettings.GetStyleSettings();
BOOL bCompBorder = (aStyleSettings.GetOptions() & (STYLE_OPTION_MACSTYLE | STYLE_OPTION_UNIXSTYLE)) == 0;
aStyleSettings.SetScrollBarSize( std::min( GetSystemMetrics( SM_CXVSCROLL ), 20 ) ); // #99956# do not allow huge scrollbars, most of the UI is not scaled anymore
aStyleSettings.SetSpinSize( std::min( GetSystemMetrics( SM_CXVSCROLL ), 20 ) );
2000-09-18 16:07:07 +00:00
aStyleSettings.SetCursorBlinkTime( GetCaretBlinkTime() );
if ( bCompBorder )
{
aStyleSettings.SetFloatTitleHeight( GetSystemMetrics( SM_CYSMCAPTION ) );
aStyleSettings.SetTitleHeight( GetSystemMetrics( SM_CYCAPTION ) );
aStyleSettings.SetActiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVEBORDER ) ) );
aStyleSettings.SetDeactiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVEBORDER ) ) );
if ( aSalShlData.mnVersion >= 410 )
{
aStyleSettings.SetActiveColor2( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTACTIVECAPTION ) ) );
aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTINACTIVECAPTION ) ) );
}
aStyleSettings.SetFaceColor( ImplWinColorToSal( GetSysColor( COLOR_3DFACE ) ) );
aStyleSettings.SetLightColor( ImplWinColorToSal( GetSysColor( COLOR_3DHILIGHT ) ) );
aStyleSettings.SetLightBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DLIGHT ) ) );
aStyleSettings.SetShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DDKSHADOW ) ) );
}
aStyleSettings.SetWorkspaceColor( ImplWinColorToSal( GetSysColor( COLOR_APPWORKSPACE ) ) );
2000-09-18 16:07:07 +00:00
aStyleSettings.SetHelpColor( ImplWinColorToSal( GetSysColor( COLOR_INFOBK ) ) );
aStyleSettings.SetHelpTextColor( ImplWinColorToSal( GetSysColor( COLOR_INFOTEXT ) ) );
aStyleSettings.SetDialogColor( aStyleSettings.GetFaceColor() );
aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() );
aStyleSettings.SetButtonTextColor( ImplWinColorToSal( GetSysColor( COLOR_BTNTEXT ) ) );
aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
aStyleSettings.SetGroupTextColor( aStyleSettings.GetRadioCheckTextColor() );
aStyleSettings.SetLabelTextColor( aStyleSettings.GetRadioCheckTextColor() );
aStyleSettings.SetInfoTextColor( aStyleSettings.GetRadioCheckTextColor() );
aStyleSettings.SetWindowColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOW ) ) );
aStyleSettings.SetWindowTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
aStyleSettings.SetFieldColor( aStyleSettings.GetWindowColor() );
aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() );
aStyleSettings.SetHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHT ) ) );
aStyleSettings.SetHighlightTextColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHTTEXT ) ) );
aStyleSettings.SetMenuHighlightColor( aStyleSettings.GetHighlightColor() );
aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetHighlightTextColor() );
if ( bCompBorder )
{
aStyleSettings.SetMenuColor( ImplWinColorToSal( GetSysColor( COLOR_MENU ) ) );
2001-11-06 09:08:39 +00:00
aStyleSettings.SetMenuBarColor( aStyleSettings.GetMenuColor() );
2000-09-18 16:07:07 +00:00
aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) );
aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) );
aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) );
aStyleSettings.SetDeactiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ) );
2001-11-06 09:08:39 +00:00
if ( aSalShlData.mbWXP )
{
// only xp supports a different menu bar color
bool bFlatMenues = false;
SystemParametersInfo( SPI_GETFLATMENU, 0, &bFlatMenues, 0);
if( bFlatMenues )
{
aStyleSettings.SetMenuBarColor( ImplWinColorToSal( GetSysColor( COLOR_MENUBAR ) ) );
aStyleSettings.SetMenuHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_MENUHILIGHT ) ) );
}
}
2000-09-18 16:07:07 +00:00
}
// Bei hellgrau geben wir die Farbe vor, damit es besser aussieht
if ( aStyleSettings.GetFaceColor() == COL_LIGHTGRAY )
aStyleSettings.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
else
{
// Checked-Color berechnen
Color aColor1 = aStyleSettings.GetFaceColor();
Color aColor2 = aStyleSettings.GetLightColor();
BYTE nRed = (BYTE)(((USHORT)aColor1.GetRed() + (USHORT)aColor2.GetRed())/2);
BYTE nGreen = (BYTE)(((USHORT)aColor1.GetGreen() + (USHORT)aColor2.GetGreen())/2);
BYTE nBlue = (BYTE)(((USHORT)aColor1.GetBlue() + (USHORT)aColor2.GetBlue())/2);
aStyleSettings.SetCheckedColor( Color( nRed, nGreen, nBlue ) );
}
2002-02-01 07:41:37 +00:00
// High contrast
HIGHCONTRAST hc;
hc.cbSize = sizeof( HIGHCONTRAST );
if( SystemParametersInfo( SPI_GETHIGHCONTRAST, hc.cbSize, &hc, 0) && (hc.dwFlags & HCF_HIGHCONTRASTON) )
aStyleSettings.SetHighContrastMode( 1 );
else
aStyleSettings.SetHighContrastMode( 0 );
2000-09-18 16:07:07 +00:00
// Query Fonts
2001-06-07 15:52:11 +00:00
Font aMenuFont = aStyleSettings.GetMenuFont();
Font aTitleFont = aStyleSettings.GetTitleFont();
Font aFloatTitleFont = aStyleSettings.GetFloatTitleFont();
Font aHelpFont = aStyleSettings.GetHelpFont();
Font aAppFont = aStyleSettings.GetAppFont();
Font aIconFont = aStyleSettings.GetIconFont();
HDC hDC = GetDC( 0 );
2001-08-23 13:16:11 +00:00
BOOL bReplaceFont = !ImplIsFontAvailable( hDC, XubString( RTL_CONSTASCII_USTRINGPARAM( "Andale Sans UI" ) ) );
2002-05-16 10:39:19 +00:00
bReplaceFont |= aStyleSettings.GetUseSystemUIFonts();
2000-09-18 16:07:07 +00:00
if ( aSalShlData.mbWNT )
{
NONCLIENTMETRICSW aNonClientMetrics;
aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
{
2001-06-07 15:52:11 +00:00
ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMenuFont, aMenuFont, bReplaceFont );
ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont, bReplaceFont );
ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont, bReplaceFont );
ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfStatusFont, aHelpFont, bReplaceFont );
ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMessageFont, aAppFont, bReplaceFont );
2000-09-18 16:07:07 +00:00
LOGFONTW aLogFont;
if ( SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) )
2001-06-07 15:52:11 +00:00
ImplSalUpdateStyleFontW( hDC, aLogFont, aIconFont, bReplaceFont );
2000-09-18 16:07:07 +00:00
}
}
else
{
NONCLIENTMETRICSA aNonClientMetrics;
aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
if ( SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
{
2001-06-07 15:52:11 +00:00
ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfMenuFont, aMenuFont, bReplaceFont );
ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont, bReplaceFont );
ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont, bReplaceFont );
ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfStatusFont, aHelpFont, bReplaceFont );
ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfMessageFont, aAppFont, bReplaceFont );
2000-09-18 16:07:07 +00:00
LOGFONTA aLogFont;
if ( SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) )
2001-06-07 15:52:11 +00:00
ImplSalUpdateStyleFontA( hDC, aLogFont, aIconFont, bReplaceFont );
2000-09-18 16:07:07 +00:00
}
}
2001-06-07 15:52:11 +00:00
ReleaseDC( 0, hDC );
2000-09-18 16:07:07 +00:00
aStyleSettings.SetMenuFont( aMenuFont );
aStyleSettings.SetTitleFont( aTitleFont );
aStyleSettings.SetFloatTitleFont( aFloatTitleFont );
aStyleSettings.SetHelpFont( aHelpFont );
aStyleSettings.SetIconFont( aIconFont );
// We prefer Arial in the russian version, because MS Sans Serif
// is to wide for the dialogs
if ( rSettings.GetInternational().GetLanguage() == LANGUAGE_RUSSIAN )
{
XubString aFontName = aAppFont.GetName();
XubString aFirstName = aFontName.GetToken( 0, ';' );
if ( aFirstName.EqualsIgnoreCaseAscii( "MS Sans Serif" ) )
{
aFontName.InsertAscii( "Arial;", 0 );
aAppFont.SetName( aFontName );
}
}
aStyleSettings.SetAppFont( aAppFont );
aStyleSettings.SetGroupFont( aAppFont );
aStyleSettings.SetLabelFont( aAppFont );
aStyleSettings.SetRadioCheckFont( aAppFont );
aStyleSettings.SetPushButtonFont( aAppFont );
aStyleSettings.SetFieldFont( aAppFont );
if ( aAppFont.GetWeight() > WEIGHT_NORMAL )
aAppFont.SetWeight( WEIGHT_NORMAL );
aStyleSettings.SetInfoFont( aAppFont );
aStyleSettings.SetToolFont( aAppFont );
WIN_BOOL bDragFull;
if ( SystemParametersInfo( SPI_GETDRAGFULLWINDOWS, 0, &bDragFull, 0 ) )
{
ULONG nDragFullOptions = aStyleSettings.GetDragFullOptions();
if ( bDragFull )
nDragFullOptions |= DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT;
else
nDragFullOptions &= ~(DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT);
aStyleSettings.SetDragFullOptions( nDragFullOptions );
}
aStyleSettings.SetIconHorzSpace( GetSystemMetrics( SM_CXICONSPACING ) );
aStyleSettings.SetIconVertSpace( GetSystemMetrics( SM_CYICONSPACING ) );
if ( RegOpenKey( HKEY_CURRENT_USER,
"Control Panel\\International\\Calendars\\TwoDigitYearMax",
&hRegKey ) == ERROR_SUCCESS )
{
BYTE aValueBuf[10];
DWORD nValue;
DWORD nValueSize = sizeof( aValueBuf );
DWORD nType;
if ( RegQueryValueEx( hRegKey, "1", 0,
&nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
{
if ( nType == REG_SZ )
{
nValue = (ULONG)ImplA2I( aValueBuf );
if ( (nValue > 1000) && (nValue < 10000) )
{
MiscSettings aMiscSettings = rSettings.GetMiscSettings();
aMiscSettings.SetTwoDigitYearStart( (USHORT)(nValue-99) );
rSettings.SetMiscSettings( aMiscSettings );
}
}
}
RegCloseKey( hRegKey );
}
rSettings.SetMouseSettings( aMouseSettings );
rSettings.SetStyleSettings( aStyleSettings );
}
// -----------------------------------------------------------------------
2001-08-23 12:45:29 +00:00
SalBitmap* SalFrame::SnapShot()
{
SalBitmap* pSalBitmap = NULL;
RECT aRect;
GetWindowRect( maFrameData.mhWnd, &aRect );
int nDX = aRect.right-aRect.left;
int nDY = aRect.bottom-aRect.top;
HDC hDC = GetWindowDC( maFrameData.mhWnd );
HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY );
HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap );
BOOL bRet;
bRet = BitBlt( hBmpDC, 0, 0, nDX, nDY, hDC, 0, 0, SRCCOPY );
ImplReleaseCachedDC( CACHED_HDC_1 );
if ( bRet )
{
pSalBitmap = new SalBitmap;
if ( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) )
{
delete pSalBitmap;
pSalBitmap = NULL;
}
}
return pSalBitmap;
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
const SystemEnvData* SalFrame::GetSystemData() const
{
return &maFrameData.maSysData;
}
// -----------------------------------------------------------------------
void SalFrame::Beep( SoundType eSoundType )
{
static UINT aImplSoundTab[5] =
{
0, // SOUND_DEFAULT
MB_ICONASTERISK, // SOUND_INFO
MB_ICONEXCLAMATION, // SOUND_WARNING
MB_ICONHAND, // SOUND_ERROR
MB_ICONQUESTION // SOUND_QUERY
};
#if SOUND_COUNT != 5
#error New Sound must be defined!
#endif
MessageBeep( aImplSoundTab[eSoundType] );
}
// -----------------------------------------------------------------------
void SalFrame::SetCallback( void* pInst, SALFRAMEPROC pProc )
{
maFrameData.mpInst = pInst;
if ( pProc )
maFrameData.mpProc = pProc;
else
maFrameData.mpProc = ImplSalCallbackDummy;
}
// -----------------------------------------------------------------------
ULONG SalFrame::GetCurrentModButtons()
{
ULONG nMod = 0;
if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
nMod |= MOUSE_LEFT;
if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
nMod |= MOUSE_MIDDLE;
if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
nMod |= MOUSE_RIGHT;
if ( GetKeyState( VK_SHIFT ) & 0x8000 )
nMod |= KEY_SHIFT;
if ( GetKeyState( VK_CONTROL ) & 0x8000 )
nMod |= KEY_MOD1;
if ( GetKeyState( VK_MENU ) & 0x8000 )
nMod |= KEY_MOD2;
return nMod;
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
static long ImplHandleMouseMsg( HWND hWnd, UINT nMsg,
WPARAM wParam, LPARAM lParam )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( !pFrame )
return 0;
if( nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN || nMsg == WM_RBUTTONDOWN )
{
// #103168# post again if async focus has not arrived yet
// hopefully we will not receive the corresponding button up before this
// button down arrives again
Window *pWin = (Window*) pFrame->maFrameData.mpInst;
if( pWin && pWin->mpFrameData->mnFocusId )
{
ImplPostMessage( hWnd, nMsg, wParam, lParam );
return 1;
}
}
2000-09-18 16:07:07 +00:00
SalMouseEvent aMouseEvt;
long nRet;
USHORT nEvent;
BOOL bCall = TRUE;
aMouseEvt.mnX = (short)LOWORD( lParam );
aMouseEvt.mnY = (short)HIWORD( lParam );
aMouseEvt.mnCode = 0;
aMouseEvt.mnTime = GetMessageTime();
// Wegen (Logitech-)MouseTreiber ueber GetKeyState() gehen, die auf
// mittlerer Maustaste Doppelklick simulieren und den KeyStatus nicht
// beruecksichtigen
if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
aMouseEvt.mnCode |= MOUSE_LEFT;
if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
aMouseEvt.mnCode |= MOUSE_MIDDLE;
if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
aMouseEvt.mnCode |= MOUSE_RIGHT;
if ( GetKeyState( VK_SHIFT ) & 0x8000 )
aMouseEvt.mnCode |= KEY_SHIFT;
if ( GetKeyState( VK_CONTROL ) & 0x8000 )
aMouseEvt.mnCode |= KEY_MOD1;
if ( GetKeyState( VK_MENU ) & 0x8000 )
aMouseEvt.mnCode |= KEY_MOD2;
switch ( nMsg )
{
case WM_MOUSEMOVE:
{
// Da bei Druecken von Modifier-Tasten die MouseEvents
// nicht zusammengefast werden (da diese durch KeyEvents
// unterbrochen werden), machen wir dieses hier selber
if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) )
{
MSG aTempMsg;
if ( ImplPeekMessage( &aTempMsg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE | PM_NOYIELD ) )
{
if ( (aTempMsg.message == WM_MOUSEMOVE) &&
(aTempMsg.wParam == wParam) )
return 1;
}
}
SalData* pSalData = GetSalData();
// Test for MouseLeave
if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) )
ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() );
2000-09-18 16:07:07 +00:00
pSalData->mhWantLeaveMsg = hWnd;
// Start MouseLeave-Timer
if ( !pSalData->mpMouseLeaveTimer )
{
pSalData->mpMouseLeaveTimer = new AutoTimer;
pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT );
pSalData->mpMouseLeaveTimer->Start();
// We dont need to set a timeout handler, because we test
// for mouseleave in the timeout callback
}
aMouseEvt.mnButton = 0;
nEvent = SALEVENT_MOUSEMOVE;
}
break;
case WM_NCMOUSEMOVE:
case SAL_MSG_MOUSELEAVE:
{
SalData* pSalData = GetSalData();
if ( pSalData->mhWantLeaveMsg == hWnd )
{
pSalData->mhWantLeaveMsg = 0;
if ( pSalData->mpMouseLeaveTimer )
{
delete pSalData->mpMouseLeaveTimer;
pSalData->mpMouseLeaveTimer = NULL;
}
// Mouse-Coordinaates are relativ to the screen
POINT aPt;
aPt.x = (short)LOWORD( lParam );
aPt.y = (short)HIWORD( lParam );
ScreenToClient( hWnd, &aPt );
aMouseEvt.mnX = aPt.x;
aMouseEvt.mnY = aPt.y;
aMouseEvt.mnButton = 0;
nEvent = SALEVENT_MOUSELEAVE;
}
else
bCall = FALSE;
}
break;
case WM_LBUTTONDOWN:
aMouseEvt.mnButton = MOUSE_LEFT;
nEvent = SALEVENT_MOUSEBUTTONDOWN;
break;
case WM_MBUTTONDOWN:
aMouseEvt.mnButton = MOUSE_MIDDLE;
nEvent = SALEVENT_MOUSEBUTTONDOWN;
break;
case WM_RBUTTONDOWN:
aMouseEvt.mnButton = MOUSE_RIGHT;
nEvent = SALEVENT_MOUSEBUTTONDOWN;
break;
case WM_LBUTTONUP:
aMouseEvt.mnButton = MOUSE_LEFT;
nEvent = SALEVENT_MOUSEBUTTONUP;
break;
case WM_MBUTTONUP:
aMouseEvt.mnButton = MOUSE_MIDDLE;
nEvent = SALEVENT_MOUSEBUTTONUP;
break;
case WM_RBUTTONUP:
aMouseEvt.mnButton = MOUSE_RIGHT;
nEvent = SALEVENT_MOUSEBUTTONUP;
break;
}
// check if this window was destroyed - this might happen if we are the help window
// and sent a mouse leave message to the application which killed the help window, ie ourself
if( !IsWindow( hWnd ) )
return 0;
2000-09-18 16:07:07 +00:00
if ( bCall )
{
if ( nEvent == SALEVENT_MOUSEBUTTONDOWN )
UpdateWindow( hWnd );
2002-07-11 06:43:29 +00:00
// --- RTL --- (mirror mouse pos)
2002-09-18 15:35:23 +00:00
if( Application::GetSettings().GetLayoutRTL() )
2002-07-11 06:43:29 +00:00
aMouseEvt.mnX = pFrame->maGeometry.nWidth-1-aMouseEvt.mnX;
2000-09-18 16:07:07 +00:00
nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
nEvent, &aMouseEvt );
if ( nMsg == WM_MOUSEMOVE )
SetCursor( pFrame->maFrameData.mhCursor );
}
else
nRet = 0;
return nRet;
}
// -----------------------------------------------------------------------
static long ImplHandleMouseActivateMsg( HWND hWnd )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( !pFrame )
return 0;
2001-10-24 07:57:18 +00:00
if ( pFrame->maFrameData.mbFloatWin )
return TRUE;
2000-09-18 16:07:07 +00:00
SalMouseActivateEvent aMouseActivateEvt;
POINT aPt;
GetCursorPos( &aPt );
ScreenToClient( hWnd, &aPt );
aMouseActivateEvt.mnX = aPt.x;
aMouseActivateEvt.mnY = aPt.y;
return pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_MOUSEACTIVATE, &aMouseActivateEvt );
}
// -----------------------------------------------------------------------
static long ImplHandleWheelMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
ImplSalYieldMutexAcquireWithWait();
long nRet = 0;
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
WORD nWinModCode = LOWORD( wParam );
POINT aWinPt;
aWinPt.x = (short)LOWORD( lParam );
aWinPt.y = (short)HIWORD( lParam );
ScreenToClient( hWnd, &aWinPt );
SalWheelMouseEvent aWheelEvt;
aWheelEvt.mnTime = GetMessageTime();
aWheelEvt.mnX = aWinPt.x;
aWheelEvt.mnY = aWinPt.y;
aWheelEvt.mnCode = 0;
aWheelEvt.mnDelta = (short)HIWORD( wParam );
aWheelEvt.mnNotchDelta = aWheelEvt.mnDelta/WHEEL_DELTA;
if ( aSalShlData.mnWheelScrollLines == WHEEL_PAGESCROLL )
aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
else
aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollLines;
aWheelEvt.mbHorz = FALSE;
if ( nWinModCode & MK_SHIFT )
aWheelEvt.mnCode |= KEY_SHIFT;
if ( nWinModCode & MK_CONTROL )
aWheelEvt.mnCode |= KEY_MOD1;
if ( GetKeyState( VK_MENU ) & 0x8000 )
aWheelEvt.mnCode |= KEY_MOD2;
// --- RTL --- (mirror mouse pos)
2002-09-18 15:35:23 +00:00
if( Application::GetSettings().GetLayoutRTL() )
aWheelEvt.mnX = pFrame->maGeometry.nWidth-1-aWheelEvt.mnX;
2000-09-18 16:07:07 +00:00
nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_WHEELMOUSE, &aWheelEvt );
}
ImplSalYieldMutexRelease();
return nRet;
}
// -----------------------------------------------------------------------
static USHORT ImplSalGetKeyCode( WPARAM wParam )
{
USHORT nKeyCode;
// convert KeyCode
if ( wParam < KEY_TAB_SIZE )
nKeyCode = aImplTranslateKeyTab[wParam];
else if ( wParam == aSalShlData.mnVKAdd )
nKeyCode = KEY_ADD;
else if ( wParam == aSalShlData.mnVKSubtract )
nKeyCode = KEY_SUBTRACT;
else if ( wParam == aSalShlData.mnVKMultiply )
nKeyCode = KEY_MULTIPLY;
else if ( wParam == aSalShlData.mnVKDivide )
nKeyCode = KEY_DIVIDE;
else if ( wParam == aSalShlData.mnVKPoint )
nKeyCode = KEY_POINT;
else if ( wParam == aSalShlData.mnVKComma )
nKeyCode = KEY_COMMA;
else if ( wParam == aSalShlData.mnVKLess )
nKeyCode = KEY_LESS;
else if ( wParam == aSalShlData.mnVKGreater )
nKeyCode = KEY_GREATER;
else if ( wParam == aSalShlData.mnVKEqual )
nKeyCode = KEY_EQUAL;
else
nKeyCode = 0;
return nKeyCode;
}
// -----------------------------------------------------------------------
static UINT ImplStrToNum( const sal_Char* pStr )
{
USHORT n = 0;
// Solange es sich um eine Ziffer handelt, String umwandeln
while( (*pStr >= 48) && (*pStr <= 57) )
{
n *= 10;
n += ((*pStr) - 48);
pStr++;
}
return n;
}
// -----------------------------------------------------------------------
static sal_Unicode ImplGetCharCode( SalFrame* pFrame, WPARAM nCharCode )
{
// If we are on Windows NT we use Unicode FrameProcs and so we
// get Unicode charcodes directly from Windows
if ( aSalShlData.mbWNT )
return (sal_Unicode)nCharCode;
UINT nLang = LOWORD( GetKeyboardLayout( 0 ) );
if ( !nLang )
{
pFrame->maFrameData.mnInputLang = 0;
pFrame->maFrameData.mnInputCodePage = GetACP();
}
else if ( nLang != pFrame->maFrameData.mnInputLang )
{
pFrame->maFrameData.mnInputLang = nLang;
sal_Char aBuf[10];
if ( GetLocaleInfoA( MAKELCID( nLang, SORT_DEFAULT ), LOCALE_IDEFAULTANSICODEPAGE,
aBuf, sizeof(aBuf) ) > 0 )
{
pFrame->maFrameData.mnInputCodePage = ImplStrToNum( aBuf );
if ( !pFrame->maFrameData.mnInputCodePage )
pFrame->maFrameData.mnInputCodePage = GetACP();
}
else
pFrame->maFrameData.mnInputCodePage = GetACP();
}
sal_Char aCharBuf[2];
int nCharLen;
WCHAR c;
if ( nCharCode > 0xFF )
{
aCharBuf[0] = (sal_Char)(nCharCode>>8);
aCharBuf[1] = (sal_Char)nCharCode;
nCharLen = 2;
}
else
{
aCharBuf[0] = (sal_Char)nCharCode;
nCharLen = 1;
}
if ( ::MultiByteToWideChar( pFrame->maFrameData.mnInputCodePage,
MB_PRECOMPOSED,
aCharBuf, nCharLen, &c, 1 ) )
return (sal_Unicode)c;
else
return (sal_Unicode)nCharCode;
}
// -----------------------------------------------------------------------
static long ImplHandleKeyMsg( HWND hWnd, UINT nMsg,
WPARAM wParam, LPARAM lParam )
{
static BOOL bIgnoreCharMsg = FALSE;
static WPARAM nDeadChar = 0;
static WPARAM nLastVKChar = 0;
static USHORT nLastChar = 0;
static USHORT nLastModKeyCode = 0;
static bool bWaitForModKeyRelease = false;
2000-09-18 16:07:07 +00:00
USHORT nRepeat = LOWORD( lParam )-1;
USHORT nModCode = 0;
// Key wurde evtl. durch SysChild an uns weitergeleitet und
// darf somit dann nicht doppelt verarbeitet werden
GetSalData()->mnSalObjWantKeyEvt = 0;
if ( nMsg == WM_DEADCHAR )
{
nDeadChar = wParam;
return 0;
}
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( !pFrame )
return 0;
// Wir restaurieren den Background-Modus bei jeder Texteingabe,
// da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
if ( pFrame->maFrameData.mpGraphics &&
pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC )
SetBkMode( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC, TRANSPARENT );
// determine modifiers
if ( GetKeyState( VK_SHIFT ) & 0x8000 )
nModCode |= KEY_SHIFT;
if ( GetKeyState( VK_CONTROL ) & 0x8000 )
nModCode |= KEY_MOD1;
if ( GetKeyState( VK_MENU ) & 0x8000 )
{
nModCode |= KEY_MOD2;
if ( !(nModCode & KEY_MOD1) &&
((nMsg == WM_SYSKEYDOWN) || (nMsg == WM_SYSKEYUP)) )
nModCode |= KEY_CONTROLMOD;
}
if ( (nMsg == WM_CHAR) || (nMsg == WM_SYSCHAR) )
{
nDeadChar = 0;
if ( bIgnoreCharMsg )
{
bIgnoreCharMsg = FALSE;
// #101635# if zero is returned here for WM_SYSCHAR (ALT+<key>) Windows will beep
// becaus this 'hotkey' was not processed -> better return 1
// except for Alt-SPACE which should always open the sysmenu (#104616#)
return ( wParam == 0x20 ) ? 0 : 1;
2000-09-18 16:07:07 +00:00
}
// Backspace ignorieren wir als eigenstaendige Taste,
// damit wir keine Probleme in Kombination mit einem
// DeadKey bekommen
if ( wParam == 0x08 ) // BACKSPACE
return 0;
// Hier kommen nur "freifliegende" WM_CHAR Message an, die durch
// eintippen einer ALT-NUMPAD Kombination erzeugt wurden
SalKeyEvent aKeyEvt;
if ( (wParam >= '0') && (wParam <= '9') )
aKeyEvt.mnCode = KEYGROUP_NUM + wParam - '0';
else if ( (wParam >= 'A') && (wParam <= 'Z') )
aKeyEvt.mnCode = KEYGROUP_ALPHA + wParam - 'A';
else if ( (wParam >= 'a') && (wParam <= 'z') )
aKeyEvt.mnCode = KEYGROUP_ALPHA + wParam - 'a';
else if ( wParam == 0x0D ) // RETURN
aKeyEvt.mnCode = KEY_RETURN;
else if ( wParam == 0x1B ) // ESCAPE
aKeyEvt.mnCode = KEY_ESCAPE;
else if ( wParam == 0x09 ) // TAB
aKeyEvt.mnCode = KEY_TAB;
else if ( wParam == 0x20 ) // SPACE
aKeyEvt.mnCode = KEY_SPACE;
else
aKeyEvt.mnCode = 0;
aKeyEvt.mnTime = GetMessageTime();
aKeyEvt.mnCode |= nModCode;
aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, wParam );
aKeyEvt.mnRepeat = nRepeat;
nLastChar = 0;
nLastVKChar = 0;
long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYINPUT, &aKeyEvt );
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYUP, &aKeyEvt );
return nRet;
}
else
{
// Bei Shift, Control und Menu schicken wir einen KeyModChange-Event
if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) )
{
SalKeyModEvent aModEvt;
aModEvt.mnTime = GetMessageTime();
aModEvt.mnCode = nModCode;
aModEvt.mnModKeyCode = 0; // no command events will be sent if this member is 0
USHORT tmpCode = 0;
if( GetKeyState( VK_LSHIFT ) & 0x8000 )
tmpCode |= MODKEY_LSHIFT;
if( GetKeyState( VK_RSHIFT ) & 0x8000 )
tmpCode |= MODKEY_RSHIFT;
if( GetKeyState( VK_LCONTROL ) & 0x8000 )
tmpCode |= MODKEY_LMOD1;
if( GetKeyState( VK_RCONTROL ) & 0x8000 )
tmpCode |= MODKEY_RMOD1;
if( GetKeyState( VK_LMENU ) & 0x8000 )
tmpCode |= MODKEY_LMOD2;
if( GetKeyState( VK_RMENU ) & 0x8000 )
tmpCode |= MODKEY_RMOD2;
if( tmpCode < nLastModKeyCode )
{
aModEvt.mnModKeyCode = nLastModKeyCode;
nLastModKeyCode = 0;
bWaitForModKeyRelease = true;
}
else
{
if( !bWaitForModKeyRelease )
nLastModKeyCode = tmpCode;
}
if( !tmpCode )
bWaitForModKeyRelease = false;
2000-09-18 16:07:07 +00:00
return pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYMODCHANGE, &aModEvt );
}
else
{
SalKeyEvent aKeyEvt;
USHORT nEvent;
MSG aCharMsg;
WIN_BOOL bCharPeek = FALSE;
UINT nCharMsg = WM_CHAR;
BOOL bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
nLastModKeyCode = 0; // make sure no modkey messages are sent if they belong to a hotkey (see above)
bWaitForModKeyRelease = true;
2000-09-18 16:07:07 +00:00
aKeyEvt.mnCode = ImplSalGetKeyCode( wParam );
if ( !bKeyUp )
{
// check for charcode
// Mit Hilfe von PeekMessage holen wir uns jetzt die
// zugehoerige WM_CHAR Message, wenn vorhanden.
// Diese WM_CHAR Message steht immer am Anfang der
// Messagequeue. Ausserdem ist sichergestellt, dass immer
// nur eine WM_CHAR Message in der Queue steht.
bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD );
if ( bCharPeek && (nDeadChar == aCharMsg.wParam) )
{
bCharPeek = FALSE;
nDeadChar = 0;
if ( wParam == VK_BACK )
{
ImplPeekMessage( &aCharMsg, hWnd,
nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
return 0;
}
}
else
{
if ( !bCharPeek )
{
bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
WM_SYSCHAR, WM_SYSCHAR, PM_NOREMOVE | PM_NOYIELD );
nCharMsg = WM_SYSCHAR;
}
}
if ( bCharPeek )
aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, aCharMsg.wParam );
else
aKeyEvt.mnCharCode = 0;
nLastChar = aKeyEvt.mnCharCode;
nLastVKChar = wParam;
}
else
{
if ( wParam == nLastVKChar )
{
aKeyEvt.mnCharCode = nLastChar;
nLastChar = 0;
nLastVKChar = 0;
}
}
if ( aKeyEvt.mnCode || aKeyEvt.mnCharCode )
{
if ( bKeyUp )
nEvent = SALEVENT_KEYUP;
else
nEvent = SALEVENT_KEYINPUT;
aKeyEvt.mnTime = GetMessageTime();
aKeyEvt.mnCode |= nModCode;
aKeyEvt.mnRepeat = nRepeat;
bIgnoreCharMsg = bCharPeek;
long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
nEvent, &aKeyEvt );
bIgnoreCharMsg = FALSE;
// char-message, than remove or ignore
if ( bCharPeek )
{
nDeadChar = 0;
if ( nRet )
{
ImplPeekMessage( &aCharMsg, hWnd,
nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
}
else
bIgnoreCharMsg = TRUE;
}
return nRet;
}
else
return 0;
}
}
}
// -----------------------------------------------------------------------
long ImplHandleSalObjKeyMsg( HWND hWnd, UINT nMsg,
WPARAM wParam, LPARAM lParam )
{
if ( (nMsg == WM_KEYDOWN) || (nMsg == WM_KEYUP) )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( !pFrame )
return 0;
USHORT nRepeat = LOWORD( lParam )-1;
USHORT nModCode = 0;
// determine modifiers
if ( GetKeyState( VK_SHIFT ) & 0x8000 )
nModCode |= KEY_SHIFT;
if ( GetKeyState( VK_CONTROL ) & 0x8000 )
nModCode |= KEY_MOD1;
if ( GetKeyState( VK_MENU ) & 0x8000 )
{
nModCode |= KEY_MOD2;
if ( !(nModCode & KEY_MOD1) )
nModCode |= KEY_CONTROLMOD;
}
if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) && (wParam != VK_MENU) )
{
SalKeyEvent aKeyEvt;
USHORT nEvent;
BOOL bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
// convert KeyCode
aKeyEvt.mnCode = ImplSalGetKeyCode( wParam );
aKeyEvt.mnCharCode = 0;
if ( aKeyEvt.mnCode )
{
if ( bKeyUp )
nEvent = SALEVENT_KEYUP;
else
nEvent = SALEVENT_KEYINPUT;
aKeyEvt.mnTime = GetMessageTime();
aKeyEvt.mnCode |= nModCode;
aKeyEvt.mnRepeat = nRepeat;
long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
nEvent, &aKeyEvt );
return nRet;
}
else
return 0;
}
}
return 0;
}
// -----------------------------------------------------------------------
long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( !pFrame )
return 0;
USHORT nRepeat = LOWORD( lParam )-1;
USHORT nModCode = 0;
USHORT cKeyCode = (USHORT)wParam;
// determine modifiers
if ( GetKeyState( VK_SHIFT ) & 0x8000 )
nModCode |= KEY_SHIFT;
if ( GetKeyState( VK_CONTROL ) & 0x8000 )
nModCode |= KEY_MOD1;
nModCode |= KEY_MOD2;
if ( !(nModCode & KEY_MOD1) )
nModCode |= KEY_CONTROLMOD;
// KeyEvent zusammenbauen
SalKeyEvent aKeyEvt;
aKeyEvt.mnTime = GetMessageTime();
if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
else if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
aKeyEvt.mnCode = KEY_A+(cKeyCode-65);
else if ( (cKeyCode >= 97) && (cKeyCode <= 122) )
aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
else
aKeyEvt.mnCode = 0;
aKeyEvt.mnCode |= nModCode;
aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, cKeyCode );
aKeyEvt.mnRepeat = nRepeat;
long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYINPUT, &aKeyEvt );
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYUP, &aKeyEvt );
return nRet;
}
// -----------------------------------------------------------------------
static void ImplHandlePaintMsg( HWND hWnd )
{
2000-12-14 12:39:14 +00:00
BOOL bMutex = FALSE;
2000-09-18 16:07:07 +00:00
if ( ImplSalYieldMutexTryToAcquire() )
2000-12-14 12:39:14 +00:00
bMutex = TRUE;
2000-09-18 16:07:07 +00:00
2000-12-14 12:39:14 +00:00
// if we don't get the mutex, we can also change the clip region,
// because other threads doesn't use the mutex from the main
// thread --> see GetGraphics()
2000-09-18 16:07:07 +00:00
2000-12-14 12:39:14 +00:00
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
2000-09-18 16:07:07 +00:00
{
2000-12-14 12:39:14 +00:00
// Clip-Region muss zurueckgesetzt werden, da wir sonst kein
// ordentliches Bounding-Rectangle bekommen
if ( pFrame->maFrameData.mpGraphics && pFrame->maFrameData.mpGraphics->maGraphicsData.mhRegion )
SelectClipRgn( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC, 0 );
// Laut Window-Doku soll man erst abfragen, ob ueberhaupt eine
// Paint-Region anliegt
if ( GetUpdateRect( hWnd, NULL, FALSE ) )
2000-09-18 16:07:07 +00:00
{
2000-12-14 12:39:14 +00:00
// Call BeginPaint/EndPaint to query the rect and send
// this Notofication to rect
RECT aUpdateRect;
PAINTSTRUCT aPs;
BeginPaint( hWnd, &aPs );
CopyRect( &aUpdateRect, &aPs.rcPaint );
EndPaint( hWnd, &aPs );
// Paint
2000-09-18 16:07:07 +00:00
// ClipRegion wieder herstellen
2000-12-14 12:39:14 +00:00
if ( pFrame->maFrameData.mpGraphics && pFrame->maFrameData.mpGraphics->maGraphicsData.mhRegion )
2000-09-18 16:07:07 +00:00
{
2000-12-14 12:39:14 +00:00
SelectClipRgn( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC,
pFrame->maFrameData.mpGraphics->maGraphicsData.mhRegion );
2000-09-18 16:07:07 +00:00
}
2000-12-14 12:39:14 +00:00
if ( bMutex )
{
SalPaintEvent aPEvt;
aPEvt.mnBoundX = aUpdateRect.left;
aPEvt.mnBoundY = aUpdateRect.top;
aPEvt.mnBoundWidth = aUpdateRect.right-aUpdateRect.left;
aPEvt.mnBoundHeight = aUpdateRect.bottom-aUpdateRect.top;
2002-07-11 06:43:29 +00:00
// --- RTL --- (mirror paint rect)
2002-09-18 15:35:23 +00:00
if( Application::GetSettings().GetLayoutRTL() )
2002-07-11 06:43:29 +00:00
aPEvt.mnBoundX = pFrame->maGeometry.nWidth-aPEvt.mnBoundWidth-aPEvt.mnBoundX;
2000-12-14 12:39:14 +00:00
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_PAINT, &aPEvt );
}
else
{
RECT* pRect = new RECT;
CopyRect( pRect, &aUpdateRect );
ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
}
}
else
{
// ClipRegion wieder herstellen
if ( pFrame->maFrameData.mpGraphics && pFrame->maFrameData.mpGraphics->maGraphicsData.mhRegion )
{
SelectClipRgn( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC,
pFrame->maFrameData.mpGraphics->maGraphicsData.mhRegion );
}
2000-09-18 16:07:07 +00:00
}
}
2000-12-14 12:39:14 +00:00
if ( bMutex )
ImplSalYieldMutexRelease();
2000-09-18 16:07:07 +00:00
}
// -----------------------------------------------------------------------
static void ImplHandlePaintMsg2( HWND hWnd, RECT* pRect )
{
// Paint
if ( ImplSalYieldMutexTryToAcquire() )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
SalPaintEvent aPEvt;
aPEvt.mnBoundX = pRect->left;
aPEvt.mnBoundY = pRect->top;
aPEvt.mnBoundWidth = pRect->right-pRect->left;
aPEvt.mnBoundHeight = pRect->bottom-pRect->top;
2002-07-11 06:43:29 +00:00
// --- RTL --- (mirror paint rect)
2002-09-18 15:35:23 +00:00
if( Application::GetSettings().GetLayoutRTL() )
2002-07-11 06:43:29 +00:00
aPEvt.mnBoundX = pFrame->maGeometry.nWidth-aPEvt.mnBoundWidth-aPEvt.mnBoundX;
2000-09-18 16:07:07 +00:00
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_PAINT, &aPEvt );
}
ImplSalYieldMutexRelease();
delete pRect;
}
else
ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
}
// -----------------------------------------------------------------------
2001-10-24 07:57:18 +00:00
static void UpdateFrameGeometry( HWND hWnd, SalFrame* pFrame )
{
if( !pFrame )
return;
RECT aRect;
GetWindowRect( hWnd, &aRect );
2001-11-23 11:39:27 +00:00
memset(&pFrame->maGeometry, 0, sizeof(SalFrameGeometry) );
2001-11-14 10:15:25 +00:00
POINT aPt;
aPt.x=0;
aPt.y=0;
ClientToScreen(hWnd, &aPt);
int cx = aPt.x - aRect.left;
pFrame->maGeometry.nTopDecoration = aPt.y - aRect.top;
2001-10-30 09:47:03 +00:00
pFrame->maGeometry.nLeftDecoration = cx;
pFrame->maGeometry.nRightDecoration = cx;
2001-10-30 09:47:03 +00:00
2001-11-14 10:15:25 +00:00
pFrame->maGeometry.nX = aPt.x;
pFrame->maGeometry.nY = aPt.y;
2001-10-24 07:57:18 +00:00
2001-11-14 10:15:25 +00:00
RECT aInnerRect;
GetClientRect( hWnd, &aInnerRect );
if( aInnerRect.bottom ) // may be zero if window was not shown yet
pFrame->maGeometry.nBottomDecoration += aRect.bottom - aPt.y - aInnerRect.bottom;
else
// bottom border is typically the same as left/right
pFrame->maGeometry.nBottomDecoration = pFrame->maGeometry.nLeftDecoration;
int nWidth = aRect.right - aRect.left
- pFrame->maGeometry.nRightDecoration - pFrame->maGeometry.nLeftDecoration;
int nHeight = aRect.bottom - aRect.top
- pFrame->maGeometry.nBottomDecoration - pFrame->maGeometry.nTopDecoration;
// clamp to zero
pFrame->maGeometry.nHeight = nHeight < 0 ? 0 : nHeight;
pFrame->maGeometry.nWidth = nWidth < 0 ? 0 : nWidth;
2001-10-24 07:57:18 +00:00
}
// -----------------------------------------------------------------------
static void ImplCallMoveHdl( HWND hWnd )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_MOVE, 0 );
// Um doppelte Paints von VCL und SAL zu vermeiden
2001-10-31 18:59:11 +00:00
//if ( IsWindowVisible( hWnd ) && !pFrame->maFrameData.mbInShow )
// UpdateWindow( hWnd );
2001-10-24 07:57:18 +00:00
}
}
// -----------------------------------------------------------------------
2002-03-21 17:35:44 +00:00
static void ImplCallClosePopupsHdl( HWND hWnd )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_CLOSEPOPUPS, 0 );
}
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
static void ImplHandleMoveMsg( HWND hWnd )
{
if ( ImplSalYieldMutexTryToAcquire() )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
2001-10-24 07:57:18 +00:00
UpdateFrameGeometry( hWnd, pFrame );
2000-09-18 16:07:07 +00:00
if ( GetWindowStyle( hWnd ) & WS_VISIBLE )
pFrame->maFrameData.mbDefPos = FALSE;
// Gegen moegliche Rekursionen sichern
if ( !pFrame->maFrameData.mbInMoveMsg )
{
// Fenster im FullScreenModus wieder einpassen
pFrame->maFrameData.mbInMoveMsg = TRUE;
if ( pFrame->maFrameData.mbFullScreen )
ImplSalFrameFullScreenPos( pFrame );
pFrame->maFrameData.mbInMoveMsg = FALSE;
}
// Status merken
ImplSaveFrameState( pFrame );
2001-10-31 18:59:11 +00:00
2001-10-24 07:57:18 +00:00
// Call Hdl
//#93851 if we call this handler, VCL floating windows are not updated correctly
2001-10-31 18:59:11 +00:00
ImplCallMoveHdl( hWnd );
2000-09-18 16:07:07 +00:00
}
ImplSalYieldMutexRelease();
}
else
ImplPostMessage( hWnd, SAL_MSG_POSTMOVE, 0, 0 );
}
// -----------------------------------------------------------------------
static void ImplCallSizeHdl( HWND hWnd )
{
// Da Windows diese Messages auch senden kann, muss hier auch die
// Solar-Semaphore beruecksichtigt werden
if ( ImplSalYieldMutexTryToAcquire() )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_RESIZE, 0 );
// Um doppelte Paints von VCL und SAL zu vermeiden
if ( IsWindowVisible( hWnd ) && !pFrame->maFrameData.mbInShow )
UpdateWindow( hWnd );
}
ImplSalYieldMutexRelease();
}
else
ImplPostMessage( hWnd, SAL_MSG_POSTCALLSIZE, 0, 0 );
}
// -----------------------------------------------------------------------
static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
if ( (wParam != SIZE_MAXSHOW) && (wParam != SIZE_MAXHIDE) )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
2001-10-24 07:57:18 +00:00
UpdateFrameGeometry( hWnd, pFrame );
2000-09-18 16:07:07 +00:00
pFrame->maFrameData.mnWidth = (int)LOWORD(lParam);
pFrame->maFrameData.mnHeight = (int)HIWORD(lParam);
// Status merken
ImplSaveFrameState( pFrame );
// Call Hdl
ImplCallSizeHdl( hWnd );
}
}
}
// -----------------------------------------------------------------------
static void ImplHandleFocusMsg( HWND hWnd )
{
if ( ImplSalYieldMutexTryToAcquire() )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame && !SalFrame::mbInReparent )
2000-09-18 16:07:07 +00:00
{
// Query the actual status
if ( ::GetFocus() == hWnd )
{
if ( IsWindowVisible( hWnd ) && !pFrame->maFrameData.mbInShow )
UpdateWindow( hWnd );
// Feststellen, ob wir IME unterstuetzen
if ( pFrame->maFrameData.mbIME && pFrame->maFrameData.mhDefIMEContext )
{
UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
pFrame->maFrameData.mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
pFrame->maFrameData.mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
pFrame->maFrameData.mbHandleIME = !pFrame->maFrameData.mbSpezIME;
}
2000-09-18 16:07:07 +00:00
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_GETFOCUS, 0 );
}
else
{
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_LOSEFOCUS, 0 );
}
}
ImplSalYieldMutexRelease();
}
else
ImplPostMessage( hWnd, SAL_MSG_POSTFOCUS, 0, 0 );
}
// -----------------------------------------------------------------------
static void ImplHandleCloseMsg( HWND hWnd )
{
if ( ImplSalYieldMutexTryToAcquire() )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_CLOSE, 0 );
}
ImplSalYieldMutexRelease();
}
else
ImplPostMessage( hWnd, WM_CLOSE, 0, 0 );
}
// -----------------------------------------------------------------------
static long ImplHandleShutDownMsg( HWND hWnd )
{
ImplSalYieldMutexAcquireWithWait();
long nRet = 0;
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_SHUTDOWN, 0 );
}
ImplSalYieldMutexRelease();
return nRet;
}
// -----------------------------------------------------------------------
static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg,
WPARAM wParam, LPARAM lParam )
{
USHORT nSalEvent = SALEVENT_SETTINGSCHANGED;
if ( nMsg == WM_DEVMODECHANGE )
nSalEvent = SALEVENT_PRINTERCHANGED;
#ifdef WM_DISPLAYCHANGE
else if ( nMsg == WM_DISPLAYCHANGE )
nSalEvent = SALEVENT_DISPLAYCHANGED;
#endif
else if ( nMsg == WM_FONTCHANGE )
nSalEvent = SALEVENT_FONTCHANGED;
else if ( nMsg == WM_TIMECHANGE )
nSalEvent = SALEVENT_DATETIMECHANGED;
else if ( nMsg == WM_WININICHANGE )
{
if ( lParam )
{
if ( aSalShlData.mbWNT )
{
if ( ImplSalWICompareAscii( (const wchar_t*)lParam, "devices" ) == 0 )
nSalEvent = SALEVENT_PRINTERCHANGED;
}
else
{
if ( stricmp( (const char*)lParam, "devices" ) == 0 )
nSalEvent = SALEVENT_PRINTERCHANGED;
}
}
}
#ifdef WM_SETTINGCHANGE
if ( nMsg == WM_SETTINGCHANGE )
{
if ( wParam == SPI_SETWHEELSCROLLLINES )
aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
}
#endif
if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal )
ImplUpdateSysColorEntries();
ImplSalYieldMutexAcquireWithWait();
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
if ( (nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE) )
{
if ( pFrame->maFrameData.mbFullScreen )
ImplSalFrameFullScreenPos( pFrame );
}
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
nSalEvent, 0 );
}
ImplSalYieldMutexRelease();
}
// -----------------------------------------------------------------------
static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam )
{
ImplSalYieldMutexAcquireWithWait();
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_USEREVENT, (void*)lParam );
}
ImplSalYieldMutexRelease();
}
// -----------------------------------------------------------------------
static void ImplHandleForcePalette( HWND hWnd )
{
SalData* pSalData = GetSalData();
HPALETTE hPal = pSalData->mhDitherPal;
if ( hPal )
{
if ( !ImplSalYieldMutexTryToAcquire() )
{
ImplPostMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
return;
}
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame && pFrame->maFrameData.mpGraphics )
{
SalGraphics* pGraphics = pFrame->maFrameData.mpGraphics;
if ( pGraphics && pGraphics->maGraphicsData.mhDefPal )
{
SelectPalette( pGraphics->maGraphicsData.mhDC, hPal, FALSE );
if ( RealizePalette( pGraphics->maGraphicsData.mhDC ) )
{
InvalidateRect( hWnd, NULL, FALSE );
UpdateWindow( hWnd );
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_DISPLAYCHANGED, 0 );
}
}
}
ImplSalYieldMutexRelease();
}
}
// -----------------------------------------------------------------------
static LRESULT ImplHandlePalette( BOOL bFrame, HWND hWnd, UINT nMsg,
WPARAM wParam, LPARAM lParam, int& rDef )
{
SalData* pSalData = GetSalData();
HPALETTE hPal = pSalData->mhDitherPal;
if ( !hPal )
return 0;
rDef = FALSE;
if ( pSalData->mbInPalChange )
return 0;
if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
{
if ( (HWND)wParam == hWnd )
return 0;
}
BOOL bReleaseMutex = FALSE;
if ( (nMsg == WM_QUERYNEWPALETTE) || (nMsg == WM_PALETTECHANGED) )
{
// Da Windows diese Messages auch sendet, muss hier auch die
// Solar-Semaphore beruecksichtigt werden
if ( ImplSalYieldMutexTryToAcquire() )
bReleaseMutex = TRUE;
else if ( nMsg == WM_QUERYNEWPALETTE )
ImplPostMessage( hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam );
else /* ( nMsg == WM_PALETTECHANGED ) */
ImplPostMessage( hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam );
}
SalVirtualDevice* pTempVD;
SalFrame* pTempFrame;
SalGraphics* pGraphics;
HDC hDC;
HPALETTE hOldPal;
UINT nCols;
BOOL bStdDC;
BOOL bUpdate;
pSalData->mbInPalChange = TRUE;
// Alle Paletten in VirDevs und Frames zuruecksetzen
pTempVD = pSalData->mpFirstVD;
while ( pTempVD )
{
pGraphics = pTempVD->maVirDevData.mpGraphics;
if ( pGraphics->maGraphicsData.mhDefPal )
{
SelectPalette( pGraphics->maGraphicsData.mhDC,
pGraphics->maGraphicsData.mhDefPal,
TRUE );
}
pTempVD = pTempVD->maVirDevData.mpNext;
}
pTempFrame = pSalData->mpFirstFrame;
while ( pTempFrame )
{
pGraphics = pTempFrame->maFrameData.mpGraphics;
if ( pGraphics && pGraphics->maGraphicsData.mhDefPal )
{
SelectPalette( pGraphics->maGraphicsData.mhDC,
pGraphics->maGraphicsData.mhDefPal,
TRUE );
}
pTempFrame = pTempFrame->maFrameData.mpNextFrame;
}
// Palette neu realizen
SalFrame* pFrame = NULL;
if ( bFrame )
pFrame = GetWindowPtr( hWnd );
if ( pFrame && pFrame->maFrameData.mpGraphics )
{
hDC = pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC;
bStdDC = TRUE;
}
else
{
hDC = GetDC( hWnd );
bStdDC = FALSE;
}
UnrealizeObject( hPal );
hOldPal = SelectPalette( hDC, hPal, TRUE );
nCols = RealizePalette( hDC );
bUpdate = nCols != 0;
if ( !bStdDC )
{
SelectPalette( hDC, hOldPal, TRUE );
ReleaseDC( hWnd, hDC );
}
// Alle Paletten in VirDevs und Frames neu setzen
pTempVD = pSalData->mpFirstVD;
while ( pTempVD )
{
pGraphics = pTempVD->maVirDevData.mpGraphics;
if ( pGraphics->maGraphicsData.mhDefPal )
{
SelectPalette( pGraphics->maGraphicsData.mhDC, hPal, TRUE );
RealizePalette( pGraphics->maGraphicsData.mhDC );
}
pTempVD = pTempVD->maVirDevData.mpNext;
}
pTempFrame = pSalData->mpFirstFrame;
while ( pTempFrame )
{
if ( pTempFrame != pFrame )
{
pGraphics = pTempFrame->maFrameData.mpGraphics;
if ( pGraphics && pGraphics->maGraphicsData.mhDefPal )
{
SelectPalette( pGraphics->maGraphicsData.mhDC, hPal, TRUE );
if ( RealizePalette( pGraphics->maGraphicsData.mhDC ) )
bUpdate = TRUE;
}
}
pTempFrame = pTempFrame->maFrameData.mpNextFrame;
}
// Wenn sich Farben geaendert haben, dann die Fenster updaten
if ( bUpdate )
{
pTempFrame = pSalData->mpFirstFrame;
while ( pTempFrame )
{
pGraphics = pTempFrame->maFrameData.mpGraphics;
if ( pGraphics && pGraphics->maGraphicsData.mhDefPal )
{
InvalidateRect( pTempFrame->maFrameData.mhWnd, NULL, FALSE );
UpdateWindow( pTempFrame->maFrameData.mhWnd );
pTempFrame->maFrameData.mpProc( pTempFrame->maFrameData.mpInst, pTempFrame,
SALEVENT_DISPLAYCHANGED, 0 );
}
pTempFrame = pTempFrame->maFrameData.mpNextFrame;
}
}
pSalData->mbInPalChange = FALSE;
if ( bReleaseMutex )
ImplSalYieldMutexRelease();
if ( nMsg == WM_PALETTECHANGED )
return 0;
else
return nCols;
}
// -----------------------------------------------------------------------
static int ImplHandleMinMax( HWND hWnd, LPARAM lParam )
{
int bRet = FALSE;
if ( ImplSalYieldMutexTryToAcquire() )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
MINMAXINFO* pMinMax = (MINMAXINFO*)lParam;
2000-09-18 16:07:07 +00:00
if ( pFrame->maFrameData.mbFullScreen )
{
int nX;
int nY;
int nDX;
int nDY;
ImplSalCalcFullScreenSize( pFrame, nX, nY, nDX, nDY );
if ( pMinMax->ptMaxPosition.x > nX )
pMinMax->ptMaxPosition.x = nX;
if ( pMinMax->ptMaxPosition.y > nY )
pMinMax->ptMaxPosition.y = nY;
if ( pMinMax->ptMaxSize.x < nDX )
pMinMax->ptMaxSize.x = nDX;
if ( pMinMax->ptMaxSize.y < nDY )
pMinMax->ptMaxSize.y = nDY;
if ( pMinMax->ptMaxTrackSize.x < nDX )
pMinMax->ptMaxTrackSize.x = nDX;
if ( pMinMax->ptMaxTrackSize.y < nDY )
pMinMax->ptMaxTrackSize.y = nDY;
pMinMax->ptMinTrackSize.x = nDX;
pMinMax->ptMinTrackSize.y = nDY;
bRet = TRUE;
}
if ( pFrame->maFrameData.mnMinWidth || pFrame->maFrameData.mnMinHeight )
{
int nMinWidth = pFrame->maFrameData.mnMinWidth;
int nMinHeight = pFrame->maFrameData.mnMinHeight;
int nLeft;
int nTop;
int nRight;
int nBottom;
ImplSalCalcBorder( pFrame, nLeft, nTop, nRight, nBottom );
nMinWidth += nLeft+nRight;
nMinHeight += nTop+nBottom;
if ( pMinMax->ptMinTrackSize.x < nMinWidth )
pMinMax->ptMinTrackSize.x = nMinWidth;
if ( pMinMax->ptMinTrackSize.y < nMinHeight )
pMinMax->ptMinTrackSize.y = nMinHeight;
}
2000-09-18 16:07:07 +00:00
}
ImplSalYieldMutexRelease();
}
return bRet;
}
// -----------------------------------------------------------------------
static int ImplHandleSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( !pFrame )
return 0;
WPARAM nCommand = wParam & 0xFFF0;
if ( pFrame->maFrameData.mbFullScreen )
{
WIN_BOOL bMaximize = IsZoomed( pFrame->maFrameData.mhWnd );
WIN_BOOL bMinimize = IsIconic( pFrame->maFrameData.mhWnd );
if ( (nCommand == SC_SIZE) ||
(!bMinimize && (nCommand == SC_MOVE)) ||
(!bMaximize && (nCommand == SC_MAXIMIZE)) ||
(bMaximize && (nCommand == SC_RESTORE)) )
{
MessageBeep( 0 );
return TRUE;
}
}
if ( nCommand == SC_KEYMENU )
{
// Hier verarbeiten wir nur KeyMenu-Events fuer Alt um
// den MenuBar zu aktivieren, oder wenn ein SysChild-Fenster
// den Focus hat, da diese Alt+Tasten-Kombinationen nur
// ueber diesen Event verarbeitet werden
if ( !LOWORD( lParam ) )
{
// Nur ausloesen, wenn keine weitere Taste gedrueckt ist. Im
// Gegensatz zur Doku wird in der X-Koordinaate der CharCode
// geliefert, der zusaetzlich gedrueckt ist
// Also 32 fuer Space, 99 fuer c, 100 fuer d, ...
// Da dies nicht dokumentiert ist, fragen wir vorsichtshalber
// auch den Status der Space-Taste ab
if ( GetKeyState( VK_SPACE ) & 0x8000 )
return 0;
// Damit nicht bei Alt+Maustaste auch der MenuBar aktiviert wird
if ( (GetKeyState( VK_LBUTTON ) & 0x8000) ||
(GetKeyState( VK_RBUTTON ) & 0x8000) ||
(GetKeyState( VK_MBUTTON ) & 0x8000) ||
(GetKeyState( VK_SHIFT ) & 0x8000) )
2000-09-18 16:07:07 +00:00
return 1;
SalKeyEvent aKeyEvt;
aKeyEvt.mnTime = GetMessageTime();
aKeyEvt.mnCode = KEY_MENU;
aKeyEvt.mnCharCode = 0;
aKeyEvt.mnRepeat = 0;
long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYINPUT, &aKeyEvt );
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYUP, &aKeyEvt );
return (nRet != 0);
}
else
{
// Testen, ob ein SysChild den Focus hat
HWND hFocusWnd = ::GetFocus();
if ( hFocusWnd && ImplFindSalObject( hFocusWnd ) )
{
char cKeyCode = (char)(unsigned char)LOWORD( lParam );
// LowerCase
if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
cKeyCode += 32;
// Wir nehmen nur 0-9 und A-Z, alle anderen Tasten muessen durch
// den Hook vom SalObj verarbeitet werden
if ( ((cKeyCode >= 48) && (cKeyCode <= 57)) ||
((cKeyCode >= 97) && (cKeyCode <= 122)) )
{
USHORT nModCode = 0;
if ( GetKeyState( VK_SHIFT ) & 0x8000 )
nModCode |= KEY_SHIFT;
if ( GetKeyState( VK_CONTROL ) & 0x8000 )
nModCode |= KEY_MOD1;
nModCode |= KEY_MOD2;
if ( !(nModCode & KEY_MOD1) )
nModCode |= KEY_CONTROLMOD;
SalKeyEvent aKeyEvt;
aKeyEvt.mnTime = GetMessageTime();
if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
else
aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
aKeyEvt.mnCode |= nModCode;
aKeyEvt.mnCharCode = cKeyCode;
aKeyEvt.mnRepeat = 0;
long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYINPUT, &aKeyEvt );
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_KEYUP, &aKeyEvt );
return (nRet != 0);
}
}
}
}
return FALSE;
}
// -----------------------------------------------------------------------
static void ImplHandleInputLangChange( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
ImplSalYieldMutexAcquireWithWait();
// Feststellen, ob wir IME unterstuetzen
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame && pFrame->maFrameData.mbIME && pFrame->maFrameData.mhDefIMEContext )
{
HWND hWnd = pFrame->maFrameData.mhWnd;
HKL hKL = (HKL)lParam;
UINT nImeProps = ImmGetProperty( hKL, IGP_PROPERTY );
pFrame->maFrameData.mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
pFrame->maFrameData.mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
pFrame->maFrameData.mbHandleIME = !pFrame->maFrameData.mbSpezIME;
}
ImplSalYieldMutexRelease();
}
// -----------------------------------------------------------------------
static void ImplUpdateIMECursorPos( SalFrame* pFrame, HIMC hIMC )
{
COMPOSITIONFORM aForm;
memset( &aForm, 0, sizeof( aForm ) );
// Cursor-Position ermitteln und aus der die Default-Position fuer
// das Composition-Fenster berechnen
SalExtTextInputPosEvent aPosEvt;
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
if ( (aPosEvt.mnX == -1) && (aPosEvt.mnY == -1) )
aForm.dwStyle |= CFS_DEFAULT;
else
{
aForm.dwStyle |= CFS_POINT;
aForm.ptCurrentPos.x = aPosEvt.mnX;
aForm.ptCurrentPos.y = aPosEvt.mnY;
}
ImmSetCompositionWindow( hIMC, &aForm );
// Because not all IME's use this values, we create
// a Windows caret to force the Position from the IME
if ( GetFocus() == pFrame->maFrameData.mhWnd )
{
CreateCaret( pFrame->maFrameData.mhWnd, 0,
aPosEvt.mnWidth, aPosEvt.mnHeight );
SetCaretPos( aPosEvt.mnX, aPosEvt.mnY );
}
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
static BOOL ImplHandleIMEStartComposition( HWND hWnd )
{
BOOL bDef = TRUE;
ImplSalYieldMutexAcquireWithWait();
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
{
2000-11-03 13:17:43 +00:00
HIMC hIMC = ImmGetContext( hWnd );
if ( hIMC )
2000-09-18 16:07:07 +00:00
{
ImplUpdateIMECursorPos( pFrame, hIMC );
2000-11-03 13:17:43 +00:00
ImmReleaseContext( hWnd, hIMC );
}
2000-09-18 16:07:07 +00:00
2000-11-03 13:17:43 +00:00
if ( pFrame->maFrameData.mbHandleIME )
{
2000-09-18 16:07:07 +00:00
if ( pFrame->maFrameData.mbAtCursorIME )
bDef = FALSE;
}
}
ImplSalYieldMutexRelease();
return bDef;
}
// -----------------------------------------------------------------------
static BOOL ImplHandleIMECompositionInput( SalFrame* pFrame,
HIMC hIMC, LPARAM lParam )
{
BOOL bDef = TRUE;
// Init Event
SalExtTextInputEvent aEvt;
aEvt.mnTime = GetMessageTime();
aEvt.mpTextAttr = NULL;
aEvt.mnCursorPos = 0;
aEvt.mnDeltaStart = 0;
aEvt.mbOnlyCursor = FALSE;
aEvt.mnCursorFlags = 0;
// If we get a result string, then we handle this input
if ( lParam & GCS_RESULTSTR )
{
bDef = FALSE;
LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, 0, 0 ) / sizeof( WCHAR );
if ( nTextLen >= 0 )
{
WCHAR* pTextBuf = new WCHAR[nTextLen];
ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
aEvt.maText = XubString( pTextBuf, (xub_StrLen)nTextLen );
delete pTextBuf;
}
aEvt.mnCursorPos = aEvt.maText.Len();
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
ImplUpdateIMECursorPos( pFrame, hIMC );
}
// If the IME doesn't support OnSpot input, then there is nothing to do
if ( !pFrame->maFrameData.mbAtCursorIME )
return !bDef;
// If we get new Composition data, then we handle this new input
if ( (lParam & (GCS_COMPSTR | GCS_COMPATTR)) ||
((lParam & GCS_CURSORPOS) && !(lParam & GCS_RESULTSTR)) )
{
bDef = FALSE;
USHORT* pSalAttrAry = NULL;
LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ) / sizeof( WCHAR );
if ( nTextLen > 0 )
{
WCHAR* pTextBuf = new WCHAR[nTextLen];
ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
aEvt.maText = XubString( pTextBuf, (xub_StrLen)nTextLen );
delete pTextBuf;
WIN_BYTE* pAttrBuf = NULL;
LONG nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, 0, 0 );
if ( nAttrLen > 0 )
{
pAttrBuf = new WIN_BYTE[nAttrLen];
ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf, nAttrLen );
}
if ( pAttrBuf )
{
xub_StrLen nTextLen = aEvt.maText.Len();
pSalAttrAry = new USHORT[nTextLen];
memset( pSalAttrAry, 0, nTextLen*sizeof( USHORT ) );
for ( xub_StrLen i = 0; (i < nTextLen) && (i < nAttrLen); i++ )
{
WIN_BYTE nWinAttr = pAttrBuf[i];
USHORT nSalAttr;
if ( nWinAttr == ATTR_TARGET_CONVERTED )
{
2002-04-12 08:56:55 +00:00
nSalAttr = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
}
else if ( nWinAttr == ATTR_CONVERTED )
nSalAttr = SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE;
else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED )
2002-04-12 08:56:55 +00:00
nSalAttr = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
else if ( nWinAttr == ATTR_INPUT_ERROR )
nSalAttr = SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
else /* ( nWinAttr == ATTR_INPUT ) */
nSalAttr = SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
pSalAttrAry[i] = nSalAttr;
}
aEvt.mpTextAttr = pSalAttrAry;
delete pAttrBuf;
}
}
// Only when we get new composition data, we must send this event
if ( (nTextLen > 0) || !(lParam & GCS_RESULTSTR) )
{
// End the mode, if the last character is deleted
if ( !nTextLen && !pFrame->maFrameData.mbCandidateMode )
{
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
}
else
{
// Because Cursor-Position and DeltaStart never updated
// from the korean input engine, we must handle this here
if ( lParam & CS_INSERTCHAR )
{
aEvt.mnCursorPos = nTextLen;
if ( aEvt.mnCursorPos && (lParam & CS_NOMOVECARET) )
aEvt.mnCursorPos--;
}
else
aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, 0, 0 ) );
if ( pFrame->maFrameData.mbCandidateMode )
aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
if ( lParam & CS_NOMOVECARET )
aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_OVERWRITE;
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
}
ImplUpdateIMECursorPos( pFrame, hIMC );
}
if ( pSalAttrAry )
delete pSalAttrAry;
}
return !bDef;
}
// -----------------------------------------------------------------------
2000-09-18 16:07:07 +00:00
static BOOL ImplHandleIMEComposition( HWND hWnd, LPARAM lParam )
{
BOOL bDef = TRUE;
2000-11-03 13:17:43 +00:00
ImplSalYieldMutexAcquireWithWait();
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame && (!lParam || (lParam & GCS_RESULTSTR)) )
2000-09-18 16:07:07 +00:00
{
2000-11-03 13:17:43 +00:00
// Wir restaurieren den Background-Modus bei jeder Texteingabe,
// da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
if ( pFrame->maFrameData.mpGraphics &&
pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC )
SetBkMode( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC, TRANSPARENT );
}
2000-09-18 16:07:07 +00:00
2000-11-03 13:17:43 +00:00
if ( pFrame && pFrame->maFrameData.mbHandleIME )
{
if ( !lParam )
{
SalExtTextInputEvent aEvt;
aEvt.mnTime = GetMessageTime();
aEvt.mpTextAttr = NULL;
aEvt.mnCursorPos = 0;
aEvt.mnDeltaStart = 0;
aEvt.mbOnlyCursor = FALSE;
aEvt.mnCursorFlags = 0;
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
}
else if ( lParam & (GCS_RESULTSTR | GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) )
2000-09-18 16:07:07 +00:00
{
HIMC hIMC = ImmGetContext( hWnd );
if ( hIMC )
{
if ( ImplHandleIMECompositionInput( pFrame, hIMC, lParam ) )
2000-11-03 13:17:43 +00:00
bDef = FALSE;
ImmReleaseContext( hWnd, hIMC );
}
2000-09-18 16:07:07 +00:00
}
}
2000-11-03 13:17:43 +00:00
ImplSalYieldMutexRelease();
2000-09-18 16:07:07 +00:00
return bDef;
}
// -----------------------------------------------------------------------
static BOOL ImplHandleIMEEndComposition( HWND hWnd )
{
BOOL bDef = TRUE;
ImplSalYieldMutexAcquireWithWait();
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame && pFrame->maFrameData.mbHandleIME )
{
if ( pFrame->maFrameData.mbAtCursorIME )
bDef = FALSE;
}
ImplSalYieldMutexRelease();
return bDef;
}
// -----------------------------------------------------------------------
static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam )
{
if ( wParam == (WPARAM)IMN_OPENCANDIDATE )
{
ImplSalYieldMutexAcquireWithWait();
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame && pFrame->maFrameData.mbHandleIME &&
pFrame->maFrameData.mbAtCursorIME )
{
// Wir wollen den Cursor hiden
pFrame->maFrameData.mbCandidateMode = TRUE;
ImplHandleIMEComposition( hWnd, GCS_CURSORPOS );
HWND hWnd = pFrame->maFrameData.mhWnd;
HIMC hIMC = ImmGetContext( hWnd );
if ( hIMC )
{
LONG nBufLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 );
if ( nBufLen >= 1 )
{
2000-11-03 13:17:43 +00:00
SalExtTextInputPosEvent aPosEvt;
2000-09-18 16:07:07 +00:00
pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame,
2000-11-03 13:17:43 +00:00
SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
2000-09-18 16:07:07 +00:00
2000-11-03 13:17:43 +00:00
// Vertical !!!
2000-09-18 16:07:07 +00:00
CANDIDATEFORM aForm;
aForm.dwIndex = 0;
aForm.dwStyle = CFS_EXCLUDE;
2000-11-03 13:17:43 +00:00
aForm.ptCurrentPos.x = aPosEvt.mnX;
aForm.ptCurrentPos.y = aPosEvt.mnY+1;
aForm.rcArea.left = aPosEvt.mnX;
aForm.rcArea.top = aPosEvt.mnY;
aForm.rcArea.right = aForm.rcArea.left+aPosEvt.mnExtWidth+1;
aForm.rcArea.bottom = aForm.rcArea.top+aPosEvt.mnHeight+1;
2000-09-18 16:07:07 +00:00
ImmSetCandidateWindow( hIMC, &aForm );
}
ImmReleaseContext( hWnd, hIMC );
}
}
ImplSalYieldMutexRelease();
}
else if ( wParam == (WPARAM)IMN_CLOSECANDIDATE )
{
ImplSalYieldMutexAcquireWithWait();
SalFrame* pFrame = GetWindowPtr( hWnd );
if ( pFrame )
pFrame->maFrameData.mbCandidateMode = FALSE;
ImplSalYieldMutexRelease();
}
}
// -----------------------------------------------------------------------
void SalTestMouseLeave()
{
SalData* pSalData = GetSalData();
if ( pSalData->mhWantLeaveMsg && !::GetCapture() )
{
POINT aPt;
GetCursorPos( &aPt );
if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) )
ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) );
}
}
// -----------------------------------------------------------------------
static int ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ,
LRESULT& rResult )
{
POINT aPt;
POINT aScreenPt;
aScreenPt.x = (short)LOWORD( lParam );
aScreenPt.y = (short)HIWORD( lParam );
// Child-Fenster suchen, welches an der entsprechenden
// Position liegt
HWND hChildWnd;
HWND hWheelWnd = hWnd;
do
{
hChildWnd = hWheelWnd;
aPt = aScreenPt;
ScreenToClient( hChildWnd, &aPt );
hWheelWnd = ChildWindowFromPointEx( hChildWnd, aPt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT );
}
while ( hWheelWnd && (hWheelWnd != hChildWnd) );
if ( hWheelWnd && (hWheelWnd != hWnd) &&
(hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) )
{
rResult = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
return FALSE;
}
return TRUE;
}
// -----------------------------------------------------------------------
LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
{
LRESULT nRet = 0;
static int bInWheelMsg = FALSE;
static int bInQueryEnd = FALSE;
2000-09-18 16:07:07 +00:00
// By WM_CRETAE we connect the frame with the window handle
if ( nMsg == WM_CREATE )
{
// Window-Instanz am Windowhandle speichern
// Can also be used for the W-Version, because the struct
// to access lpCreateParams is the same structure
CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam;
SalFrame* pFrame = (SalFrame*)pStruct->lpCreateParams;
SetWindowPtr( hWnd, pFrame );
// HWND schon hier setzen, da schon auf den Instanzdaten
// gearbeitet werden kann, wenn Messages waehrend
// CreateWindow() gesendet werden
pFrame->maFrameData.mhWnd = hWnd;
pFrame->maFrameData.maSysData.hWnd = hWnd;
return 0;
}
switch( nMsg )
{
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
case WM_NCMOUSEMOVE:
case SAL_MSG_MOUSELEAVE:
ImplSalYieldMutexAcquireWithWait();
rDef = !ImplHandleMouseMsg( hWnd, nMsg, wParam, lParam );
ImplSalYieldMutexRelease();
break;
2001-11-06 09:08:39 +00:00
case WM_NCLBUTTONDOWN:
case WM_NCMBUTTONDOWN:
case WM_NCRBUTTONDOWN:
ImplSalYieldMutexAcquireWithWait();
2002-03-21 17:35:44 +00:00
ImplCallClosePopupsHdl( hWnd ); // close popups...
2001-11-06 09:08:39 +00:00
ImplSalYieldMutexRelease();
break;
2000-09-18 16:07:07 +00:00
case WM_MOUSEACTIVATE:
if ( LOWORD( lParam ) == HTCLIENT )
{
ImplSalYieldMutexAcquireWithWait();
nRet = ImplHandleMouseActivateMsg( hWnd );
ImplSalYieldMutexRelease();
if ( nRet )
{
nRet = MA_NOACTIVATE;
rDef = FALSE;
}
}
break;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_DEADCHAR:
case WM_CHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
ImplSalYieldMutexAcquireWithWait();
rDef = !ImplHandleKeyMsg( hWnd, nMsg, wParam, lParam );
ImplSalYieldMutexRelease();
break;
case WM_MOUSEWHEEL:
// Gegen Rekursion absichern, falls wir vom IE oder dem externen
// Fenster die Message wieder zurueckbekommen
if ( !bInWheelMsg )
{
bInWheelMsg++;
rDef = !ImplHandleWheelMsg( hWnd, wParam, lParam );
// Wenn wir die Message nicht ausgewertet haben, schauen wir
// noch einmal nach, ob dort ein geplugtes Fenster steht,
// welches wir dann benachrichtigen
if ( rDef )
rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
bInWheelMsg--;
}
break;
case WM_SYSCOMMAND:
ImplSalYieldMutexAcquireWithWait();
nRet = ImplHandleSysCommand( hWnd, wParam, lParam );
ImplSalYieldMutexRelease();
if ( nRet )
rDef = FALSE;
break;
case WM_MOVE:
case SAL_MSG_POSTMOVE:
ImplHandleMoveMsg( hWnd );
rDef = FALSE;
break;
case WM_SIZE:
ImplHandleSizeMsg( hWnd, wParam, lParam );
rDef = FALSE;
break;
case SAL_MSG_POSTCALLSIZE:
ImplCallSizeHdl( hWnd );
rDef = FALSE;
break;
case WM_GETMINMAXINFO:
if ( ImplHandleMinMax( hWnd, lParam ) )
rDef = FALSE;
break;
case WM_ERASEBKGND:
nRet = 1;
rDef = FALSE;
break;
case WM_PAINT:
ImplHandlePaintMsg( hWnd );
rDef = FALSE;
break;
case SAL_MSG_POSTPAINT:
ImplHandlePaintMsg2( hWnd, (RECT*)wParam );
rDef = FALSE;
break;
case SAL_MSG_FORCEPALETTE:
ImplHandleForcePalette( hWnd );
rDef = FALSE;
break;
case WM_QUERYNEWPALETTE:
case SAL_MSG_POSTQUERYNEWPAL:
nRet = ImplHandlePalette( TRUE, hWnd, nMsg, wParam, lParam, rDef );
break;
case WM_ACTIVATE:
// Wenn wir aktiviert werden, dann wollen wir auch unsere
// Palette setzen. Wir machen dieses in Activate,
// damit andere externe Child-Fenster auch unsere Palette
// ueberschreiben koennen. So wird unsere jedenfalls nur einmal
// gesetzt und nicht immer rekursiv, da an allen anderen Stellen
// diese nur als Background-Palette gesetzt wird
if ( LOWORD( wParam ) != WA_INACTIVE )
ImplSendMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
break;
case WM_ENABLE:
// #95133# a system dialog is opened/closed, using our app window as parent
{
SalFrame* pFrame = GetWindowPtr( hWnd );
Window *pWin = NULL;
if( pFrame )
pWin = ((Window*)pFrame->maFrameData.mpInst);
if( !wParam )
{
ImplGetSVData()->maAppData.mnModalMode++;
if( pWin )
pWin->EnableInput( FALSE, TRUE, TRUE, NULL );
}
else
{
ImplGetSVData()->maAppData.mnModalMode--;
if( pWin )
pWin->EnableInput( TRUE, TRUE, TRUE, NULL );
}
}
break;
2000-09-18 16:07:07 +00:00
case WM_KILLFOCUS:
DestroyCaret();
case WM_SETFOCUS:
2000-09-18 16:07:07 +00:00
case SAL_MSG_POSTFOCUS:
ImplHandleFocusMsg( hWnd );
rDef = FALSE;
break;
case WM_CLOSE:
ImplHandleCloseMsg( hWnd );
rDef = FALSE;
break;
case WM_QUERYENDSESSION:
if( !bInQueryEnd )
{
// handle queryendsession only once
bInQueryEnd = TRUE;
nRet = !ImplHandleShutDownMsg( hWnd );
rDef = FALSE;
}
else
{
ImplSalYieldMutexAcquireWithWait();
ImplSalYieldMutexRelease();
rDef = TRUE;
}
break;
case WM_ENDSESSION:
if( !wParam )
bInQueryEnd = FALSE; // no shutdown: allow query again
nRet = FALSE;
2000-09-18 16:07:07 +00:00
rDef = FALSE;
break;
#ifdef WM_DISPLAYCHANGE
case WM_DISPLAYCHANGE:
#endif
#ifdef WM_SETTINGCHANGE
case WM_SETTINGCHANGE:
#else
case WM_WININICHANGE:
#endif
case WM_DEVMODECHANGE:
case WM_FONTCHANGE:
case WM_SYSCOLORCHANGE:
case WM_TIMECHANGE:
ImplHandleSettingsChangeMsg( hWnd, nMsg, wParam, lParam );
break;
case SAL_MSG_USEREVENT:
ImplHandleUserEvent( hWnd, lParam );
rDef = FALSE;
break;
case SAL_MSG_CAPTUREMOUSE:
SetCapture( hWnd );
rDef = FALSE;
break;
case SAL_MSG_RELEASEMOUSE:
if ( ::GetCapture() == hWnd )
ReleaseCapture();
rDef = FALSE;
break;
case SAL_MSG_TOTOP:
ImplSalToTop( hWnd, (USHORT)wParam );
rDef = FALSE;
break;
case SAL_MSG_SHOW:
2002-07-16 08:04:37 +00:00
ImplSalShow( hWnd, (BOOL)wParam, (BOOL)lParam );
2000-09-18 16:07:07 +00:00
rDef = FALSE;
break;
2001-06-22 13:15:50 +00:00
case SAL_MSG_SETINPUTCONTEXT:
ImplSalFrameSetInputContext( hWnd, (const SalInputContext*)(void*)lParam );
rDef = FALSE;
break;
case SAL_MSG_ENDEXTTEXTINPUT:
ImplSalFrameEndExtTextInput( hWnd, (USHORT)(ULONG)(void*)wParam );
rDef = FALSE;
break;
2000-09-18 16:07:07 +00:00
case WM_INPUTLANGCHANGE:
ImplHandleInputLangChange( hWnd, wParam, lParam );
break;
case WM_IME_CHAR:
// #103487#, some IMEs (eg, those that do not work onspot)
// may send WM_IME_CHAR instead of WM_IME_COMPOSITION
// we just handle it like a WM_CHAR message - seems to work fine
ImplSalYieldMutexAcquireWithWait();
rDef = !ImplHandleKeyMsg( hWnd, WM_CHAR, wParam, lParam );
ImplSalYieldMutexRelease();
break;
case WM_IME_STARTCOMPOSITION:
2000-09-18 16:07:07 +00:00
rDef = ImplHandleIMEStartComposition( hWnd );
break;
case WM_IME_COMPOSITION:
rDef = ImplHandleIMEComposition( hWnd, lParam );
break;
case WM_IME_ENDCOMPOSITION:
rDef = ImplHandleIMEEndComposition( hWnd );
break;
case WM_IME_NOTIFY:
ImplHandleIMENotify( hWnd, wParam );
break;
}
// WheelMouse-Message abfangen
if ( rDef && (nMsg == aSalShlData.mnWheelMsgId) && aSalShlData.mnWheelMsgId )
{
// Gegen Rekursion absichern, falls wir vom IE oder dem externen
// Fenster die Message wieder zurueckbekommen
if ( !bInWheelMsg )
{
bInWheelMsg++;
// Zuerst wollen wir die Message dispatchen und dann darf auch
// das SystemWindow drankommen
WORD nKeyState = 0;
if ( GetKeyState( VK_SHIFT ) & 0x8000 )
nKeyState |= MK_SHIFT;
if ( GetKeyState( VK_CONTROL ) & 0x8000 )
nKeyState |= MK_CONTROL;
// Mutex handling is inside from this call
rDef = !ImplHandleWheelMsg( hWnd, MAKEWPARAM( nKeyState, (WORD)wParam ), lParam );
if ( rDef )
{
HWND hWheelWnd = ::GetFocus();
if ( hWheelWnd && (hWheelWnd != hWnd) )
{
nRet = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
rDef = FALSE;
}
else
rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
}
bInWheelMsg--;
}
}
return nRet;
}
LRESULT CALLBACK SalFrameWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
{
int bDef = TRUE;
LRESULT nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
if ( bDef )
nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
return nRet;
}
LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
{
int bDef = TRUE;
LRESULT nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
if ( bDef )
nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
return nRet;
}
// -----------------------------------------------------------------------
BOOL ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult )
{
// Hier verarbeiten wir alle Messages, die fuer alle Frame-Fenster gelten,
// damit diese nur einmal verarbeitet werden
// Must work for Unicode and none Unicode
if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
{
int bDef = TRUE;
rlResult = ImplHandlePalette( FALSE, hWnd, nMsg, wParam, lParam, bDef );
return (bDef != 0);
}
else
return FALSE;
}
2002-07-05 15:04:53 +00:00
// -----------------------------------------------------------------------
bool GetSalSystemDisplayInfo( System::DisplayInfo& rInfo )
{
RECT aRect;
2002-11-20 16:15:33 +00:00
ImplSalGetWorkArea( NULL, &aRect, NULL );
2002-07-05 15:04:53 +00:00
HDC hDC;
if( hDC = GetDC( NULL ) )
{
rInfo.nWidth = aRect.right - aRect.left;
rInfo.nHeight = aRect.bottom - aRect.top;
rInfo.nDepth = GetDeviceCaps( hDC, BITSPIXEL );
ReleaseDC( NULL, hDC );
return true;
}
else
return false;
}
2002-07-11 06:43:29 +00:00
// -----------------------------------------------------------------------
/* We have to map the button identifier to the identifier used by the Win32
Platform SDK to specify the default button for the MessageBox API.
The first dimension is the button combination, the second dimension
is the button identifier.
*/
static int DEFAULT_BTN_MAPPING_TABLE[][8] =
{
// Undefined OK CANCEL ABORT RETRY IGNORE YES NO
{ MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //OK
{ MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //OK_CANCEL
{ MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //ABORT_RETRY_IGNO
{ MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON3, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2 }, //YES_NO_CANCEL
{ MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2 }, //YES_NO
{ MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 } //RETRY_CANCEL
};
int ImplShowNativeMessageBox(const String& rTitle, const String& rMessage, int nButtonCombination, int nDefaultButton)
{
DBG_ASSERT( nButtonCombination >= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK &&
nButtonCombination <= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL &&
nDefaultButton >= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK &&
nDefaultButton <= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, "Invalid arguments!" );
int nFlags = MB_TASKMODAL | MB_SETFOREGROUND | nButtonCombination;
if (nButtonCombination >= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK &&
nButtonCombination <= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL &&
nDefaultButton >= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK &&
nDefaultButton <= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO)
nFlags |= DEFAULT_BTN_MAPPING_TABLE[nButtonCombination][nDefaultButton];
return MessageBoxW(
0,
rMessage.GetBuffer(),
rTitle.GetBuffer(),
nFlags);
}
// -----------------------------------------------------------------------