update dev300-m58
[ooovba.git] / vcl / win / source / window / salframe.cxx
blobb1e84e28f22dc2498c2914f40c470927768894ae
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 // i72022: ad-hoc to forcibly enable reconversion
32 #if WINVER < 0x0500
33 #undef WINVER
34 #define WINVER 0x0500
35 #endif
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/container/XIndexAccess.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/awt/Rectangle.hpp>
41 #include <comphelper/processfactory.hxx>
43 #include <string.h>
44 #include <limits.h>
46 #include <stdio.h>
48 #ifndef _SVWIN_HXX
49 #include <tools/svwin.h>
50 #endif
51 #ifdef __MINGW32__
52 #include <excpt.h>
53 #endif
54 #include <rtl/string.h>
55 #include <rtl/ustring.h>
57 #include <osl/module.h>
58 #include <tools/debug.hxx>
60 // Warning in SDK header
61 #if defined(_MSC_VER) && (_MSC_VER > 1400)
62 #pragma warning( disable: 4242 4244 )
63 #endif
64 #include <wincomp.hxx>
65 #ifndef _SV_SALIDS_HRC
66 #include <salids.hrc>
67 #endif
68 #include <vcl/sysdata.hxx>
69 #include <saldata.hxx>
70 #include <salinst.h>
71 #include <salbmp.h>
72 #include <salgdi.h>
73 #include <salsys.h>
74 #include <salframe.h>
75 #include <salvd.h>
76 #include <salmenu.h>
77 #include <salobj.h>
78 #include <vcl/impbmp.hxx>
79 #include <vcl/timer.hxx>
80 #include <saltimer.h>
81 #include <vcl/settings.hxx>
82 #ifndef _SV_KEYCOES_HXX
83 #include <vcl/keycodes.hxx>
84 #endif
85 #include <vcl/window.h>
86 #include <vcl/window.hxx>
87 #include <vcl/wrkwin.hxx>
88 #include <vcl/sallayout.hxx>
89 #include <vcl/svapp.hxx>
90 #ifndef _VCL_IMPDEL_HXX
91 #include <impdel.hxx>
92 #endif
93 #define COMPILE_MULTIMON_STUBS
94 #include <multimon.h>
95 #include <vector>
96 #ifdef __MINGW32__
97 #include <algorithm>
98 using ::std::max;
99 #endif
101 #include <com/sun/star/uno/Exception.hdl>
103 #include <time.h>
105 using ::rtl::OUString;
106 using namespace ::com::sun::star::uno;
107 using namespace ::com::sun::star::lang;
108 using namespace ::com::sun::star::container;
109 using namespace ::com::sun::star::beans;
111 // The following defines are newly added in Longhorn
112 #ifndef WM_MOUSEHWHEEL
113 # define WM_MOUSEHWHEEL 0x020E
114 #endif
115 #ifndef SPI_GETWHEELSCROLLCHARS
116 # define SPI_GETWHEELSCROLLCHARS 0x006C
117 #endif
118 #ifndef SPI_SETWHEELSCROLLCHARS
119 # define SPI_SETWHEELSCROLLCHARS 0x006D
120 #endif
124 #if OSL_DEBUG_LEVEL > 1
125 void MyOutputDebugString( char *s) { OutputDebugString( s ); }
126 #endif
128 // misssing prototypes and constants for LayeredWindows
129 extern "C" {
130 //WINUSERAPI BOOL WINAPI SetLayeredWindowAttributes(HWND,COLORREF,BYTE,DWORD);
131 typedef BOOL ( WINAPI * SetLayeredWindowAttributes_Proc_T ) (HWND,COLORREF,BYTE,DWORD);
132 static SetLayeredWindowAttributes_Proc_T lpfnSetLayeredWindowAttributes;
135 // =======================================================================
137 const unsigned int WM_USER_SYSTEM_WINDOW_ACTIVATED = RegisterWindowMessageA("SYSTEM_WINDOW_ACTIVATED");
139 BOOL WinSalFrame::mbInReparent = FALSE;
141 // =======================================================================
143 // Wegen Fehler in Windows-Headerfiles
144 #ifndef IMN_OPENCANDIDATE
145 #define IMN_OPENCANDIDATE 0x0005
146 #endif
147 #ifndef IMN_CLOSECANDIDATE
148 #define IMN_CLOSECANDIDATE 0x0004
149 #endif
151 #ifndef WM_THEMECHANGED
152 #define WM_THEMECHANGED 0x031A
153 #endif
155 // Macros for support of WM_UNICHAR & Keyman 6.0
156 #define Uni_UTF32ToSurrogate1(ch) (((unsigned long) (ch) - 0x10000) / 0x400 + 0xD800)
157 #define Uni_UTF32ToSurrogate2(ch) (((unsigned long) (ch) - 0x10000) % 0x400 + 0xDC00)
158 #define Uni_SupplementaryPlanesStart 0x10000
160 // =======================================================================
162 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame );
163 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame );
165 static void ImplSaveFrameState( WinSalFrame* pFrame )
167 // Position, Groesse und Status fuer GetWindowState() merken
168 if ( !pFrame->mbFullScreen )
170 BOOL bVisible = (GetWindowStyle( pFrame->mhWnd ) & WS_VISIBLE) != 0;
171 if ( IsIconic( pFrame->mhWnd ) )
173 pFrame->maState.mnState |= SAL_FRAMESTATE_MINIMIZED;
174 if ( bVisible )
175 pFrame->mnShowState = SW_SHOWMAXIMIZED;
177 else if ( IsZoomed( pFrame->mhWnd ) )
179 pFrame->maState.mnState &= ~SAL_FRAMESTATE_MINIMIZED;
180 pFrame->maState.mnState |= SAL_FRAMESTATE_MAXIMIZED;
181 if ( bVisible )
182 pFrame->mnShowState = SW_SHOWMAXIMIZED;
183 pFrame->mbRestoreMaximize = TRUE;
185 else
187 RECT aRect;
188 GetWindowRect( pFrame->mhWnd, &aRect );
190 // to be consistent with Unix, the frame state is without(!) decoration
191 RECT aRect2 = aRect;
192 AdjustWindowRectEx( &aRect2, GetWindowStyle( pFrame->mhWnd ),
193 FALSE, GetWindowExStyle( pFrame->mhWnd ) );
194 long nTopDeco = abs( aRect.top - aRect2.top );
195 long nLeftDeco = abs( aRect.left - aRect2.left );
196 long nBottomDeco = abs( aRect.bottom - aRect2.bottom );
197 long nRightDeco = abs( aRect.right - aRect2.right );
199 pFrame->maState.mnState &= ~(SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED);
200 // subtract decoration
201 pFrame->maState.mnX = aRect.left+nLeftDeco;
202 pFrame->maState.mnY = aRect.top+nTopDeco;
203 pFrame->maState.mnWidth = aRect.right-aRect.left-nLeftDeco-nRightDeco;
204 pFrame->maState.mnHeight = aRect.bottom-aRect.top-nTopDeco-nBottomDeco;
205 if ( bVisible )
206 pFrame->mnShowState = SW_SHOWNORMAL;
207 pFrame->mbRestoreMaximize = FALSE;
212 // -----------------------------------------------------------------------
214 // if pParentRect is set, the workarea of the monitor that contains pParentRect is returned
215 void ImplSalGetWorkArea( HWND hWnd, RECT *pRect, const RECT *pParentRect )
217 static int winVerChecked = 0;
218 static int winVerOk = 0;
220 // check if we or our parent is fullscreen, then the taskbar should be ignored
221 bool bIgnoreTaskbar = false;
222 WinSalFrame* pFrame = GetWindowPtr( hWnd );
223 if( pFrame )
225 Window *pWin = pFrame->GetWindow();
226 while( pWin )
228 WorkWindow *pWorkWin = (pWin->GetType() == WINDOW_WORKWINDOW) ? (WorkWindow *) pWin : NULL;
229 if( pWorkWin && pWorkWin->ImplGetWindowImpl()->mbReallyVisible && pWorkWin->IsFullScreenMode() )
231 bIgnoreTaskbar = true;
232 break;
234 else
235 pWin = pWin->ImplGetWindowImpl()->mpParent;
239 if( !winVerChecked )
241 winVerChecked = 1;
242 winVerOk = 1;
244 // multi monitor calls not available on Win95/NT
245 if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
247 if ( aSalShlData.maVersionInfo.dwMajorVersion <= 4 )
248 winVerOk = 0; // NT
250 else if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
252 if ( aSalShlData.maVersionInfo.dwMajorVersion == 4 && aSalShlData.maVersionInfo.dwMinorVersion == 0 )
253 winVerOk = 0; // Win95
257 // calculates the work area taking multiple monitors into account
258 if( winVerOk )
260 static int nMonitors = GetSystemMetrics( SM_CMONITORS );
261 if( nMonitors == 1 )
263 if( bIgnoreTaskbar )
265 pRect->left = pRect->top = 0;
266 pRect->right = GetSystemMetrics( SM_CXSCREEN );
267 pRect->bottom = GetSystemMetrics( SM_CYSCREEN );
269 else
270 SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 );
272 else
274 if( pParentRect != NULL )
276 // return the size of the monitor where pParentRect lives
277 HMONITOR hMonitor;
278 MONITORINFO mi;
280 // get the nearest monitor to the passed rect.
281 hMonitor = MonitorFromRect(pParentRect, MONITOR_DEFAULTTONEAREST);
283 // get the work area or entire monitor rect.
284 mi.cbSize = sizeof(mi);
285 GetMonitorInfo(hMonitor, &mi);
286 if( !bIgnoreTaskbar )
287 *pRect = mi.rcWork;
288 else
289 *pRect = mi.rcMonitor;
291 else
293 // return the union of all monitors
294 pRect->left = GetSystemMetrics( SM_XVIRTUALSCREEN );
295 pRect->top = GetSystemMetrics( SM_YVIRTUALSCREEN );
296 pRect->right = pRect->left + GetSystemMetrics( SM_CXVIRTUALSCREEN );
297 pRect->bottom = pRect->top + GetSystemMetrics( SM_CYVIRTUALSCREEN );
299 // virtualscreen does not take taskbar into account, so use the corresponding
300 // diffs between screen and workarea from the default screen
301 // however, this is still not perfect: the taskbar might not be on the primary screen
302 if( !bIgnoreTaskbar )
304 RECT wRect, scrRect;
305 SystemParametersInfo( SPI_GETWORKAREA, 0, &wRect, 0 );
306 scrRect.left = 0;
307 scrRect.top = 0;
308 scrRect.right = GetSystemMetrics( SM_CXSCREEN );
309 scrRect.bottom = GetSystemMetrics( SM_CYSCREEN );
311 pRect->left += wRect.left;
312 pRect->top += wRect.top;
313 pRect->right -= scrRect.right - wRect.right;
314 pRect->bottom -= scrRect.bottom - wRect.bottom;
319 else
321 if( bIgnoreTaskbar )
323 pRect->left = pRect->top = 0;
324 pRect->right = GetSystemMetrics( SM_CXSCREEN );
325 pRect->bottom = GetSystemMetrics( SM_CYSCREEN );
327 else
328 SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 );
332 // =======================================================================
334 SalFrame* ImplSalCreateFrame( WinSalInstance* pInst,
335 HWND hWndParent, ULONG nSalFrameStyle )
337 WinSalFrame* pFrame = new WinSalFrame;
338 HWND hWnd;
339 DWORD nSysStyle = 0;
340 DWORD nExSysStyle = 0;
341 BOOL bSubFrame = FALSE;
343 if( getenv( "SAL_SYNCHRONIZE" ) ) // no buffering of drawing commands
344 GdiSetBatchLimit( 1 );
346 static int bLayeredAPI = -1;
347 if( bLayeredAPI == -1 )
349 bLayeredAPI = 0;
350 // check for W2k and XP
351 if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
353 OUString aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "user32" ) );
354 oslModule pLib = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
355 oslGenericFunction pFunc = NULL;
356 if( pLib )
357 pFunc = osl_getAsciiFunctionSymbol( pLib, "SetLayeredWindowAttributes" );
359 lpfnSetLayeredWindowAttributes = ( SetLayeredWindowAttributes_Proc_T ) pFunc;
361 bLayeredAPI = pFunc ? 1 : 0;
364 static const char* pEnvTransparentFloats = getenv("SAL_TRANSPARENT_FLOATS" );
366 // determine creation data
367 if ( nSalFrameStyle & (SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_SYSTEMCHILD) )
369 nSysStyle |= WS_CHILD;
370 if( nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD )
371 nSysStyle |= WS_CLIPSIBLINGS;
373 else
375 // #i87402# commenting out WS_CLIPCHILDREN
376 // this breaks SAL_FRAME_STYLE_SYSTEMCHILD handling, which is not
377 // used currently. Probably SAL_FRAME_STYLE_SYSTEMCHILD should be
378 // removed again.
380 // nSysStyle |= WS_CLIPCHILDREN;
381 if ( hWndParent )
383 nSysStyle |= WS_POPUP;
384 bSubFrame = TRUE;
385 pFrame->mbNoIcon = TRUE;
387 else
389 // Only with WS_OVRLAPPED we get a useful default position/size
390 if ( (nSalFrameStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE)) ==
391 (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE) )
392 nSysStyle |= WS_OVERLAPPED;
393 else
395 nSysStyle |= WS_POPUP;
396 if ( !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) )
397 nExSysStyle |= WS_EX_TOOLWINDOW; // avoid taskbar appearance, for eg splash screen
401 if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
403 pFrame->mbCaption = TRUE;
404 nSysStyle |= WS_SYSMENU | WS_CAPTION;
405 if ( !hWndParent )
406 nSysStyle |= WS_SYSMENU | WS_MINIMIZEBOX;
407 else
408 nExSysStyle |= WS_EX_DLGMODALFRAME;
410 if ( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE )
412 pFrame->mbSizeBorder = TRUE;
413 nSysStyle |= WS_THICKFRAME;
414 if ( !hWndParent )
415 nSysStyle |= WS_MAXIMIZEBOX;
417 else
418 pFrame->mbFixBorder = TRUE;
420 if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT )
421 nExSysStyle |= WS_EX_APPWINDOW;
423 if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW
424 // #100656# toolwindows lead to bad alt-tab behaviour, if they have the focus
425 // you must press it twice to leave the application
426 // so toolwindows are only used for non sizeable windows
427 // which are typically small, so a small caption makes sense
429 // #103578# looked too bad - above changes reverted
430 /* && !(nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE) */ )
432 pFrame->mbNoIcon = TRUE;
433 nExSysStyle |= WS_EX_TOOLWINDOW;
434 if ( pEnvTransparentFloats && bLayeredAPI == 1 /*&& !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) */)
435 nExSysStyle |= WS_EX_LAYERED;
438 if ( nSalFrameStyle & SAL_FRAME_STYLE_FLOAT )
440 nExSysStyle |= WS_EX_TOOLWINDOW;
441 pFrame->mbFloatWin = TRUE;
443 if ( pEnvTransparentFloats && bLayeredAPI == 1 /*&& !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) */)
444 nExSysStyle |= WS_EX_LAYERED;
447 if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLTIP )
448 nExSysStyle |= WS_EX_TOPMOST;
450 // init frame data
451 pFrame->mnStyle = nSalFrameStyle;
453 // determine show style
454 pFrame->mnShowState = SW_SHOWNORMAL;
455 if ( (nSysStyle & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME) )
457 if ( GetSystemMetrics( SM_CXSCREEN ) <= 1024 )
458 pFrame->mnShowState = SW_SHOWMAXIMIZED;
459 else
461 if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT )
463 SalData* pSalData = GetSalData();
464 pFrame->mnShowState = pSalData->mnCmdShow;
465 if ( (pFrame->mnShowState != SW_SHOWMINIMIZED) &&
466 (pFrame->mnShowState != SW_MINIMIZE) &&
467 (pFrame->mnShowState != SW_SHOWMINNOACTIVE) )
469 if ( (pFrame->mnShowState == SW_SHOWMAXIMIZED) ||
470 (pFrame->mnShowState == SW_MAXIMIZE) )
471 pFrame->mbOverwriteState = FALSE;
472 pFrame->mnShowState = SW_SHOWMAXIMIZED;
474 else
475 pFrame->mbOverwriteState = FALSE;
477 else
479 // Document Windows are also maximized, if the current Document Window
480 // is also maximized
481 HWND hWnd = GetForegroundWindow();
482 if ( hWnd && IsMaximized( hWnd ) &&
483 (GetWindowInstance( hWnd ) == pInst->mhInst) &&
484 ((GetWindowStyle( hWnd ) & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME)) )
485 pFrame->mnShowState = SW_SHOWMAXIMIZED;
490 // create frame
491 if ( aSalShlData.mbWNT )
493 LPCWSTR pClassName;
494 if ( bSubFrame )
496 if ( nSalFrameStyle & (SAL_FRAME_STYLE_MOVEABLE|SAL_FRAME_STYLE_NOSHADOW) ) // check if shadow not wanted
497 pClassName = SAL_SUBFRAME_CLASSNAMEW;
498 else
499 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW; // undecorated floaters will get shadow on XP
501 else
503 if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
504 pClassName = SAL_FRAME_CLASSNAMEW;
505 else
506 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW;
508 hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
509 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
510 hWndParent, 0, pInst->mhInst, (void*)pFrame );
511 if( !hWnd )
512 ImplWriteLastError( GetLastError(), "CreateWindowEx" );
513 #if OSL_DEBUG_LEVEL > 1
514 // set transparency value
515 if( bLayeredAPI == 1 && GetWindowExStyle( hWnd ) & WS_EX_LAYERED )
516 lpfnSetLayeredWindowAttributes( hWnd, 0, 230, 0x00000002 /*LWA_ALPHA*/ );
517 #endif
519 else
521 LPCSTR pClassName;
522 if ( bSubFrame )
523 pClassName = SAL_SUBFRAME_CLASSNAMEA;
524 else
525 pClassName = SAL_FRAME_CLASSNAMEA;
526 hWnd = CreateWindowExA( nExSysStyle, pClassName, "", nSysStyle,
527 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
528 hWndParent, 0, pInst->mhInst, (void*)pFrame );
530 if ( !hWnd )
532 delete pFrame;
533 return NULL;
536 // If we have an Window with an Caption Bar and without
537 // an MaximizeBox, we change the SystemMenu
538 if ( (nSysStyle & (WS_CAPTION | WS_MAXIMIZEBOX)) == (WS_CAPTION) )
540 HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
541 if ( hSysMenu )
543 if ( !(nSysStyle & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX)) )
544 DeleteMenu( hSysMenu, SC_RESTORE, MF_BYCOMMAND );
545 else
546 EnableMenuItem( hSysMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
547 if ( !(nSysStyle & WS_MINIMIZEBOX) )
548 DeleteMenu( hSysMenu, SC_MINIMIZE, MF_BYCOMMAND );
549 if ( !(nSysStyle & WS_MAXIMIZEBOX) )
550 DeleteMenu( hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND );
551 if ( !(nSysStyle & WS_THICKFRAME) )
552 DeleteMenu( hSysMenu, SC_SIZE, MF_BYCOMMAND );
555 if ( (nSysStyle & WS_SYSMENU) && !(nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE) )
557 HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
558 if ( hSysMenu )
559 EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
562 // reset input context
563 pFrame->mhDefIMEContext = ImmAssociateContext( hWnd, 0 );
565 // determine output size and state
566 RECT aRect;
567 GetClientRect( hWnd, &aRect );
568 pFrame->mnWidth = aRect.right;
569 pFrame->mnHeight = aRect.bottom;
570 ImplSaveFrameState( pFrame );
571 pFrame->mbDefPos = TRUE;
573 UpdateFrameGeometry( hWnd, pFrame );
575 if( pFrame->mnShowState == SW_SHOWMAXIMIZED )
577 // #96084 set a useful internal window size because
578 // the window will not be maximized (and the size updated) before show()
580 SetMaximizedFrameGeometry( hWnd, pFrame );
583 return pFrame;
586 // helper that only creates the HWND
587 // to allow for easy reparenting of system windows, (i.e. destroy and create new)
588 HWND ImplSalReCreateHWND( HWND hWndParent, HWND oldhWnd, BOOL bAsChild )
590 HINSTANCE hInstance = GetSalData()->mhInst;
591 ULONG nSysStyle = GetWindowLong( oldhWnd, GWL_STYLE );
592 ULONG nExSysStyle = GetWindowLong( oldhWnd, GWL_EXSTYLE );
594 if( bAsChild )
596 nSysStyle = WS_CHILD;
597 nExSysStyle = 0;
600 HWND hWnd = NULL;
601 if ( aSalShlData.mbWNT )
603 LPCWSTR pClassName = SAL_SUBFRAME_CLASSNAMEW;
604 hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
605 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
606 hWndParent, 0, hInstance, (void*)GetWindowPtr( oldhWnd ) );
608 else
610 LPCSTR pClassName = SAL_SUBFRAME_CLASSNAMEA;
611 hWnd = CreateWindowExA( nExSysStyle, pClassName, "", nSysStyle,
612 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
613 hWndParent, 0, hInstance, (void*)GetWindowPtr( oldhWnd ) );
615 return hWnd;
618 // =======================================================================
620 // Uebersetzungstabelle von System-Keycodes in StarView-Keycodes
621 #define KEY_TAB_SIZE 146
623 static USHORT aImplTranslateKeyTab[KEY_TAB_SIZE] =
625 // StarView-Code System-Code Index
626 0, // 0
627 0, // VK_LBUTTON 1
628 0, // VK_RBUTTON 2
629 0, // VK_CANCEL 3
630 0, // VK_MBUTTON 4
631 0, // 5
632 0, // 6
633 0, // 7
634 KEY_BACKSPACE, // VK_BACK 8
635 KEY_TAB, // VK_TAB 9
636 0, // 10
637 0, // 11
638 0, // VK_CLEAR 12
639 KEY_RETURN, // VK_RETURN 13
640 0, // 14
641 0, // 15
642 0, // VK_SHIFT 16
643 0, // VK_CONTROL 17
644 0, // VK_MENU 18
645 0, // VK_PAUSE 19
646 0, // VK_CAPITAL 20
647 0, // VK_HANGUL 21
648 0, // 22
649 0, // 23
650 0, // 24
651 KEY_HANGUL_HANJA, // VK_HANJA 25
652 0, // 26
653 KEY_ESCAPE, // VK_ESCAPE 27
654 0, // 28
655 0, // 29
656 0, // 30
657 0, // 31
658 KEY_SPACE, // VK_SPACE 32
659 KEY_PAGEUP, // VK_PRIOR 33
660 KEY_PAGEDOWN, // VK_NEXT 34
661 KEY_END, // VK_END 35
662 KEY_HOME, // VK_HOME 36
663 KEY_LEFT, // VK_LEFT 37
664 KEY_UP, // VK_UP 38
665 KEY_RIGHT, // VK_RIGHT 39
666 KEY_DOWN, // VK_DOWN 40
667 0, // VK_SELECT 41
668 0, // VK_PRINT 42
669 0, // VK_EXECUTE 43
670 0, // VK_SNAPSHOT 44
671 KEY_INSERT, // VK_INSERT 45
672 KEY_DELETE, // VK_DELETE 46
673 KEY_HELP, // VK_HELP 47
674 KEY_0, // 48
675 KEY_1, // 49
676 KEY_2, // 50
677 KEY_3, // 51
678 KEY_4, // 52
679 KEY_5, // 53
680 KEY_6, // 54
681 KEY_7, // 55
682 KEY_8, // 56
683 KEY_9, // 57
684 0, // 58
685 0, // 59
686 0, // 60
687 0, // 61
688 0, // 62
689 0, // 63
690 0, // 64
691 KEY_A, // 65
692 KEY_B, // 66
693 KEY_C, // 67
694 KEY_D, // 68
695 KEY_E, // 69
696 KEY_F, // 70
697 KEY_G, // 71
698 KEY_H, // 72
699 KEY_I, // 73
700 KEY_J, // 74
701 KEY_K, // 75
702 KEY_L, // 76
703 KEY_M, // 77
704 KEY_N, // 78
705 KEY_O, // 79
706 KEY_P, // 80
707 KEY_Q, // 81
708 KEY_R, // 82
709 KEY_S, // 83
710 KEY_T, // 84
711 KEY_U, // 85
712 KEY_V, // 86
713 KEY_W, // 87
714 KEY_X, // 88
715 KEY_Y, // 89
716 KEY_Z, // 90
717 0, // VK_LWIN 91
718 0, // VK_RWIN 92
719 KEY_CONTEXTMENU, // VK_APPS 93
720 0, // 94
721 0, // 95
722 KEY_0, // VK_NUMPAD0 96
723 KEY_1, // VK_NUMPAD1 97
724 KEY_2, // VK_NUMPAD2 98
725 KEY_3, // VK_NUMPAD3 99
726 KEY_4, // VK_NUMPAD4 100
727 KEY_5, // VK_NUMPAD5 101
728 KEY_6, // VK_NUMPAD6 102
729 KEY_7, // VK_NUMPAD7 103
730 KEY_8, // VK_NUMPAD8 104
731 KEY_9, // VK_NUMPAD9 105
732 KEY_MULTIPLY, // VK_MULTIPLY 106
733 KEY_ADD, // VK_ADD 107
734 KEY_DECIMAL, // VK_SEPARATOR 108
735 KEY_SUBTRACT, // VK_SUBTRACT 109
736 KEY_DECIMAL, // VK_DECIMAL 110
737 KEY_DIVIDE, // VK_DIVIDE 111
738 KEY_F1, // VK_F1 112
739 KEY_F2, // VK_F2 113
740 KEY_F3, // VK_F3 114
741 KEY_F4, // VK_F4 115
742 KEY_F5, // VK_F5 116
743 KEY_F6, // VK_F6 117
744 KEY_F7, // VK_F7 118
745 KEY_F8, // VK_F8 119
746 KEY_F9, // VK_F9 120
747 KEY_F10, // VK_F10 121
748 KEY_F11, // VK_F11 122
749 KEY_F12, // VK_F12 123
750 KEY_F13, // VK_F13 124
751 KEY_F14, // VK_F14 125
752 KEY_F15, // VK_F15 126
753 KEY_F16, // VK_F16 127
754 KEY_F17, // VK_F17 128
755 KEY_F18, // VK_F18 129
756 KEY_F19, // VK_F19 130
757 KEY_F20, // VK_F20 131
758 KEY_F21, // VK_F21 132
759 KEY_F22, // VK_F22 133
760 KEY_F23, // VK_F23 134
761 KEY_F24, // VK_F24 135
762 0, // 136
763 0, // 137
764 0, // 138
765 0, // 139
766 0, // 140
767 0, // 141
768 0, // 142
769 0, // 143
770 0, // NUMLOCK 144
771 0 // SCROLLLOCK 145
774 // =======================================================================
776 static UINT ImplSalGetWheelScrollLines()
778 UINT nScrLines = 0;
779 HWND hWndMsWheel = WIN_FindWindow( MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE );
780 if ( hWndMsWheel )
782 UINT nGetScrollLinesMsgId = RegisterWindowMessage( MSH_SCROLL_LINES );
783 nScrLines = (UINT)ImplSendMessage( hWndMsWheel, nGetScrollLinesMsgId, 0, 0 );
786 if ( !nScrLines )
787 if( !SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &nScrLines, 0 ) )
788 nScrLines = 0 ;
790 if ( !nScrLines )
791 nScrLines = 3;
793 return nScrLines;
796 // -----------------------------------------------------------------------
798 static UINT ImplSalGetWheelScrollChars()
800 UINT nScrChars = 0;
801 if( !SystemParametersInfo( SPI_GETWHEELSCROLLCHARS, 0, &nScrChars, 0 ) )
803 // Depending on Windows version, use proper default or 1 (when
804 // driver emulates hscroll)
805 if( VER_PLATFORM_WIN32_NT == aSalShlData.maVersionInfo.dwPlatformId &&
806 aSalShlData.maVersionInfo.dwMajorVersion < 6 )
808 // Windows 2000 & WinXP : emulating driver, use step size
809 // of 1
810 return 1;
812 else
814 // Longhorn or above: use proper default value of 3
815 return 3;
819 // system settings successfully read
820 return nScrChars;
823 // -----------------------------------------------------------------------
825 static void ImplSalAddBorder( const WinSalFrame* pFrame, int& width, int& height )
827 // transform client size into window size
828 RECT aWinRect;
829 aWinRect.left = 0;
830 aWinRect.right = width-1;
831 aWinRect.top = 0;
832 aWinRect.bottom = height-1;
833 AdjustWindowRectEx( &aWinRect, GetWindowStyle( pFrame->mhWnd ),
834 FALSE, GetWindowExStyle( pFrame->mhWnd ) );
835 width = aWinRect.right - aWinRect.left + 1;
836 height = aWinRect.bottom - aWinRect.top + 1;
839 // -----------------------------------------------------------------------
841 static void ImplSalCalcFullScreenSize( const WinSalFrame* pFrame,
842 int& rX, int& rY, int& rDX, int& rDY )
844 // set window to screen size
845 int nFrameX;
846 int nFrameY;
847 int nCaptionY;
848 int nScreenX = 0;
849 int nScreenY = 0;
850 int nScreenDX = 0;
851 int nScreenDY = 0;
853 if ( pFrame->mbSizeBorder )
855 nFrameX = GetSystemMetrics( SM_CXSIZEFRAME );
856 nFrameY = GetSystemMetrics( SM_CYSIZEFRAME );
858 else if ( pFrame->mbFixBorder )
860 nFrameX = GetSystemMetrics( SM_CXFIXEDFRAME );
861 nFrameY = GetSystemMetrics( SM_CYFIXEDFRAME );
863 else if ( pFrame->mbBorder )
865 nFrameX = GetSystemMetrics( SM_CXBORDER );
866 nFrameY = GetSystemMetrics( SM_CYBORDER );
868 else
870 nFrameX = 0;
871 nFrameY = 0;
873 if ( pFrame->mbCaption )
874 nCaptionY = GetSystemMetrics( SM_CYCAPTION );
875 else
876 nCaptionY = 0;
880 Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
881 Reference< XIndexAccess > xMultiMon( xFactory->createInstance(OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DisplayAccess" ) ) ), UNO_QUERY_THROW );
882 if( (pFrame->mnDisplay >= 0) && (pFrame->mnDisplay < xMultiMon->getCount()) )
884 Reference< XPropertySet > xMonitor( xMultiMon->getByIndex( pFrame->mnDisplay ), UNO_QUERY_THROW );
885 com::sun::star::awt::Rectangle aRect;
886 if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect )
888 nScreenX = aRect.X;
889 nScreenY = aRect.Y;
890 nScreenDX = aRect.Width+1; // difference between java/awt convention and vcl
891 nScreenDY = aRect.Height+1; // difference between java/awt convention and vcl
894 else
896 nScreenX = GetSystemMetrics( SM_XVIRTUALSCREEN );
897 nScreenY = GetSystemMetrics( SM_YVIRTUALSCREEN );
898 nScreenDX = GetSystemMetrics( SM_CXVIRTUALSCREEN );
899 nScreenDY = GetSystemMetrics( SM_CYVIRTUALSCREEN );
902 catch( Exception& )
906 if( !nScreenDX || !nScreenDY )
908 nScreenDX = GetSystemMetrics( SM_CXSCREEN );
909 nScreenDY = GetSystemMetrics( SM_CYSCREEN );
912 rX = nScreenX -nFrameX;
913 rY = nScreenY -(nFrameY+nCaptionY);
914 rDX = nScreenDX+(nFrameX*2);
915 rDY = nScreenDY+(nFrameY*2)+nCaptionY;
918 // -----------------------------------------------------------------------
920 static void ImplSalFrameFullScreenPos( WinSalFrame* pFrame, BOOL bAlways = FALSE )
922 if ( bAlways || !IsIconic( pFrame->mhWnd ) )
924 // set window to screen size
925 int nX;
926 int nY;
927 int nWidth;
928 int nHeight;
929 ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight );
930 SetWindowPos( pFrame->mhWnd, 0,
931 nX, nY, nWidth, nHeight,
932 SWP_NOZORDER | SWP_NOACTIVATE );
936 // -----------------------------------------------------------------------
938 WinSalFrame::WinSalFrame()
940 SalData* pSalData = GetSalData();
942 mhWnd = 0;
943 mhCursor = LoadCursor( 0, IDC_ARROW );
944 mhDefIMEContext = 0;
945 mpGraphics = NULL;
946 mpGraphics2 = NULL;
947 mnShowState = SW_SHOWNORMAL;
948 mnWidth = 0;
949 mnHeight = 0;
950 mnMinWidth = 0;
951 mnMinHeight = 0;
952 mnMaxWidth = SHRT_MAX;
953 mnMaxHeight = SHRT_MAX;
954 mnInputLang = 0;
955 mnInputCodePage = 0;
956 mbGraphics = FALSE;
957 mbCaption = FALSE;
958 mbBorder = FALSE;
959 mbFixBorder = FALSE;
960 mbSizeBorder = FALSE;
961 mbFullScreen = FALSE;
962 mbPresentation = FALSE;
963 mbInShow = FALSE;
964 mbRestoreMaximize = FALSE;
965 mbInMoveMsg = FALSE;
966 mbInSizeMsg = FALSE;
967 mbFullScreenToolWin = FALSE;
968 mbDefPos = TRUE;
969 mbOverwriteState = TRUE;
970 mbIME = FALSE;
971 mbHandleIME = FALSE;
972 mbSpezIME = FALSE;
973 mbAtCursorIME = FALSE;
974 mbCandidateMode = FALSE;
975 mbFloatWin = FALSE;
976 mbNoIcon = FALSE;
977 mSelectedhMenu = 0;
978 mLastActivatedhMenu = 0;
979 mpClipRgnData = NULL;
980 mbFirstClipRect = TRUE;
981 mpNextClipRect = NULL;
982 mnDisplay = 0;
984 memset( &maState, 0, sizeof( SalFrameState ) );
985 maSysData.nSize = sizeof( SystemEnvData );
987 memset( &maGeometry, 0, sizeof( maGeometry ) );
989 // Daten ermitteln, wenn erster Frame angelegt wird
990 if ( !pSalData->mpFirstFrame )
992 if ( !aSalShlData.mnWheelMsgId )
993 aSalShlData.mnWheelMsgId = RegisterWindowMessage( MSH_MOUSEWHEEL );
994 if ( !aSalShlData.mnWheelScrollLines )
995 aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
996 if ( !aSalShlData.mnWheelScrollChars )
997 aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars();
1000 // insert frame in framelist
1001 mpNextFrame = pSalData->mpFirstFrame;
1002 pSalData->mpFirstFrame = this;
1005 // -----------------------------------------------------------------------
1006 void WinSalFrame::updateScreenNumber()
1008 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
1009 if( pSys )
1011 const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
1012 pSys->getMonitors();
1013 Point aPoint( maGeometry.nX, maGeometry.nY );
1014 size_t nMon = rMonitors.size();
1015 for( size_t i = 0; i < nMon; i++ )
1017 if( rMonitors[i].m_aArea.IsInside( aPoint ) )
1019 mnDisplay = static_cast<sal_Int32>(i);
1020 maGeometry.nScreenNumber = static_cast<unsigned int>(i);
1026 // -----------------------------------------------------------------------
1028 WinSalFrame::~WinSalFrame()
1030 SalData* pSalData = GetSalData();
1032 if( mpClipRgnData )
1033 delete [] (BYTE*)mpClipRgnData;
1035 // remove frame from framelist
1036 WinSalFrame** ppFrame = &pSalData->mpFirstFrame;
1037 for(; (*ppFrame != this) && *ppFrame; ppFrame = &(*ppFrame)->mpNextFrame );
1038 if( *ppFrame )
1039 *ppFrame = mpNextFrame;
1040 mpNextFrame = NULL;
1042 // Release Cache DC
1043 if ( mpGraphics2 &&
1044 mpGraphics2->mhDC )
1045 ReleaseGraphics( mpGraphics2 );
1047 // destroy saved DC
1048 if ( mpGraphics )
1050 if ( mpGraphics->mhDefPal )
1051 SelectPalette( mpGraphics->mhDC, mpGraphics->mhDefPal, TRUE );
1052 ImplSalDeInitGraphics( mpGraphics );
1053 ReleaseDC( mhWnd, mpGraphics->mhDC );
1054 delete mpGraphics;
1055 mpGraphics = NULL;
1058 if ( mhWnd )
1060 // reset mouse leave data
1061 if ( pSalData->mhWantLeaveMsg == mhWnd )
1063 pSalData->mhWantLeaveMsg = 0;
1064 if ( pSalData->mpMouseLeaveTimer )
1066 delete pSalData->mpMouseLeaveTimer;
1067 pSalData->mpMouseLeaveTimer = NULL;
1071 // destroy system frame
1072 if ( !DestroyWindow( mhWnd ) )
1073 SetWindowPtr( mhWnd, 0 );
1075 mhWnd = 0;
1079 // -----------------------------------------------------------------------
1081 SalGraphics* WinSalFrame::GetGraphics()
1083 if ( mbGraphics )
1084 return NULL;
1086 // Other threads get an own DC, because Windows modify in the
1087 // other case our DC (changing clip region), when they send a
1088 // WM_ERASEBACKGROUND message
1089 SalData* pSalData = GetSalData();
1090 if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
1092 // We use only three CacheDC's for all threads, because W9x is limited
1093 // to max. 5 Cache DC's per thread
1094 if ( pSalData->mnCacheDCInUse >= 3 )
1095 return NULL;
1097 if ( !mpGraphics2 )
1099 mpGraphics2 = new WinSalGraphics;
1100 mpGraphics2->mhDC = 0;
1101 mpGraphics2->mhWnd = mhWnd;
1102 mpGraphics2->mbPrinter = FALSE;
1103 mpGraphics2->mbVirDev = FALSE;
1104 mpGraphics2->mbWindow = TRUE;
1105 mpGraphics2->mbScreen = TRUE;
1108 HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1109 SAL_MSG_GETDC,
1110 (WPARAM)mhWnd, 0 );
1111 if ( hDC )
1113 mpGraphics2->mhDC = hDC;
1114 if ( pSalData->mhDitherPal )
1116 mpGraphics2->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1117 RealizePalette( hDC );
1119 ImplSalInitGraphics( mpGraphics2 );
1120 mbGraphics = TRUE;
1122 pSalData->mnCacheDCInUse++;
1123 return mpGraphics2;
1125 else
1126 return NULL;
1128 else
1130 if ( !mpGraphics )
1132 HDC hDC = GetDC( mhWnd );
1133 if ( hDC )
1135 mpGraphics = new WinSalGraphics;
1136 mpGraphics->mhDC = hDC;
1137 mpGraphics->mhWnd = mhWnd;
1138 mpGraphics->mbPrinter = FALSE;
1139 mpGraphics->mbVirDev = FALSE;
1140 mpGraphics->mbWindow = TRUE;
1141 mpGraphics->mbScreen = TRUE;
1142 if ( pSalData->mhDitherPal )
1144 mpGraphics->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1145 RealizePalette( hDC );
1147 ImplSalInitGraphics( mpGraphics );
1148 mbGraphics = TRUE;
1151 else
1152 mbGraphics = TRUE;
1154 return mpGraphics;
1158 // -----------------------------------------------------------------------
1160 void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
1162 if ( mpGraphics2 == pGraphics )
1164 if ( mpGraphics2->mhDC )
1166 SalData* pSalData = GetSalData();
1167 if ( mpGraphics2->mhDefPal )
1168 SelectPalette( mpGraphics2->mhDC, mpGraphics2->mhDefPal, TRUE );
1169 ImplSalDeInitGraphics( mpGraphics2 );
1170 ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1171 SAL_MSG_RELEASEDC,
1172 (WPARAM)mhWnd,
1173 (LPARAM)mpGraphics2->mhDC );
1174 mpGraphics2->mhDC = 0;
1175 pSalData->mnCacheDCInUse--;
1179 mbGraphics = FALSE;
1182 // -----------------------------------------------------------------------
1184 BOOL WinSalFrame::PostEvent( void* pData )
1186 return (BOOL)ImplPostMessage( mhWnd, SAL_MSG_USEREVENT, 0, (LPARAM)pData );
1189 // -----------------------------------------------------------------------
1191 void WinSalFrame::SetTitle( const XubString& rTitle )
1193 DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::SetTitle(): WCHAR != sal_Unicode" );
1195 if ( !SetWindowTextW( mhWnd, reinterpret_cast<LPCWSTR>(rTitle.GetBuffer()) ) )
1197 ByteString aAnsiTitle = ImplSalGetWinAnsiString( rTitle );
1198 SetWindowTextA( mhWnd, aAnsiTitle.GetBuffer() );
1202 // -----------------------------------------------------------------------
1204 void WinSalFrame::SetIcon( USHORT nIcon )
1206 // If we have a window without an Icon (for example a dialog), ignore this call
1207 if ( mbNoIcon )
1208 return;
1210 // 0 means default (class) icon
1211 HICON hIcon = NULL, hSmIcon = NULL;
1212 if ( !nIcon )
1213 nIcon = 1;
1215 ImplLoadSalIcon( nIcon, hIcon, hSmIcon );
1217 DBG_ASSERT( hIcon , "WinSalFrame::SetIcon(): Could not load large icon !" );
1218 DBG_ASSERT( hSmIcon , "WinSalFrame::SetIcon(): Could not load small icon !" );
1220 ImplSendMessage( mhWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );
1221 ImplSendMessage( mhWnd, WM_SETICON, ICON_SMALL, (LPARAM)hSmIcon );
1224 // -----------------------------------------------------------------------
1226 void WinSalFrame::SetMenu( SalMenu* pSalMenu )
1228 WinSalMenu* pWMenu = static_cast<WinSalMenu*>(pSalMenu);
1229 if( pSalMenu && pWMenu->mbMenuBar )
1230 ::SetMenu( mhWnd, pWMenu->mhMenu );
1233 void WinSalFrame::DrawMenuBar()
1235 ::DrawMenuBar( mhWnd );
1238 // -----------------------------------------------------------------------
1239 HWND ImplGetParentHwnd( HWND hWnd )
1241 WinSalFrame* pFrame = GetWindowPtr( hWnd );
1242 if( !pFrame || !pFrame->GetWindow())
1243 return ::GetParent( hWnd );
1244 Window *pRealParent = pFrame->GetWindow()->ImplGetWindowImpl()->mpRealParent;
1245 if( pRealParent )
1246 return static_cast<WinSalFrame*>(pRealParent->ImplGetWindowImpl()->mpFrame)->mhWnd;
1247 else
1248 return ::GetParent( hWnd );
1252 // -----------------------------------------------------------------------
1254 SalFrame* WinSalFrame::GetParent() const
1256 return GetWindowPtr( ImplGetParentHwnd( mhWnd ) );
1259 // -----------------------------------------------------------------------
1261 static void ImplSalShow( HWND hWnd, BOOL bVisible, BOOL bNoActivate )
1263 WinSalFrame* pFrame = GetWindowPtr( hWnd );
1264 if ( !pFrame )
1265 return;
1267 if ( bVisible )
1269 pFrame->mbDefPos = FALSE;
1270 pFrame->mbOverwriteState = TRUE;
1271 pFrame->mbInShow = TRUE;
1273 // #i4715, save position
1274 RECT aRectPreMatrox, aRectPostMatrox;
1275 GetWindowRect( hWnd, &aRectPreMatrox );
1277 vcl::DeletionListener aDogTag( pFrame );
1278 if( bNoActivate )
1279 ShowWindow( hWnd, SW_SHOWNOACTIVATE );
1280 else
1281 ShowWindow( hWnd, pFrame->mnShowState );
1282 if( aDogTag.isDeleted() )
1283 return;
1285 if ( aSalShlData.mbWXP && pFrame->mbFloatWin && !(pFrame->mnStyle & SAL_FRAME_STYLE_NOSHADOW))
1287 // erase the window immediately to improve XP shadow effect
1288 // otherwise the shadow may appears long time before the rest of the window
1289 // especially when accessibility is on
1290 HDC dc = GetDC( hWnd );
1291 RECT aRect;
1292 GetClientRect( hWnd, &aRect );
1293 FillRect( dc, &aRect, (HBRUSH) (COLOR_MENU+1) ); // choose the menucolor, because its mostly noticeable for menues
1294 ReleaseDC( hWnd, dc );
1297 // #i4715, matrox centerpopup might have changed our position
1298 // reposition popups without caption (menues, dropdowns, tooltips)
1299 GetWindowRect( hWnd, &aRectPostMatrox );
1300 if( (GetWindowStyle( hWnd ) & WS_POPUP) &&
1301 !pFrame->mbCaption &&
1302 (aRectPreMatrox.left != aRectPostMatrox.left || aRectPreMatrox.top != aRectPostMatrox.top) )
1303 SetWindowPos( hWnd, 0, aRectPreMatrox.left, aRectPreMatrox.top, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE );
1305 if( aDogTag.isDeleted() )
1306 return;
1307 Window *pClientWin = pFrame->GetWindow()->ImplGetClientWindow();
1308 if ( pFrame->mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
1309 pFrame->mnShowState = SW_SHOWNOACTIVATE;
1310 else
1311 pFrame->mnShowState = SW_SHOW;
1312 // Damit Taskleiste unter W98 auch gleich ausgeblendet wird
1313 if ( pFrame->mbPresentation )
1315 HWND hWndParent = ::GetParent( hWnd );
1316 if ( hWndParent )
1317 SetForegroundWindow( hWndParent );
1318 SetForegroundWindow( hWnd );
1321 pFrame->mbInShow = FALSE;
1322 pFrame->updateScreenNumber();
1324 // Direct Paint only, if we get the SolarMutx
1325 if ( ImplSalYieldMutexTryToAcquire() )
1327 UpdateWindow( hWnd );
1328 ImplSalYieldMutexRelease();
1331 else
1333 // See also Bug #91813# and #68467#
1334 if ( pFrame->mbFullScreen &&
1335 pFrame->mbPresentation &&
1336 (aSalShlData.mnVersion < 500) &&
1337 !::GetParent( hWnd ) )
1339 // Damit im Impress-Player in der Taskleiste nicht durch
1340 // einen Windows-Fehler hin- und wieder mal ein leerer
1341 // Button stehen bleibt, muessen wir hier die Taskleiste
1342 // etwas austricksen. Denn wenn wir im FullScreenMode sind
1343 // und das Fenster hiden kommt Windows anscheinend etwas aus
1344 // dem tritt und somit minimieren wir das Fenster damit es
1345 // nicht flackert
1346 ANIMATIONINFO aInfo;
1347 aInfo.cbSize = sizeof( aInfo );
1348 SystemParametersInfo( SPI_GETANIMATION, 0, &aInfo, 0 );
1349 if ( aInfo.iMinAnimate )
1351 int nOldAni = aInfo.iMinAnimate;
1352 aInfo.iMinAnimate = 0;
1353 SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 );
1354 ShowWindow( pFrame->mhWnd, SW_SHOWMINNOACTIVE );
1355 aInfo.iMinAnimate = nOldAni;
1356 SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 );
1358 else
1359 ShowWindow( hWnd, SW_SHOWMINNOACTIVE );
1360 ShowWindow( hWnd, SW_HIDE );
1362 else
1363 ShowWindow( hWnd, SW_HIDE );
1367 // -----------------------------------------------------------------------
1370 void WinSalFrame::SetExtendedFrameStyle( SalExtStyle )
1374 // -----------------------------------------------------------------------
1376 void WinSalFrame::Show( BOOL bVisible, BOOL bNoActivate )
1378 // Post this Message to the window, because this only works
1379 // in the thread of the window, which has create this window.
1380 // We post this message to avoid deadlocks
1381 if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
1382 ImplPostMessage( mhWnd, SAL_MSG_SHOW, bVisible, bNoActivate );
1383 else
1384 ImplSalShow( mhWnd, bVisible, bNoActivate );
1387 // -----------------------------------------------------------------------
1389 void WinSalFrame::Enable( BOOL bEnable )
1391 EnableWindow( mhWnd, bEnable );
1394 // -----------------------------------------------------------------------
1396 void WinSalFrame::SetMinClientSize( long nWidth, long nHeight )
1398 mnMinWidth = nWidth;
1399 mnMinHeight = nHeight;
1402 void WinSalFrame::SetMaxClientSize( long nWidth, long nHeight )
1404 mnMaxWidth = nWidth;
1405 mnMaxHeight = nHeight;
1408 // -----------------------------------------------------------------------
1410 void WinSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight,
1411 USHORT nFlags )
1413 BOOL bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
1414 if ( !bVisible )
1416 Window *pClientWin = GetWindow()->ImplGetClientWindow();
1417 if ( mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
1418 mnShowState = SW_SHOWNOACTIVATE;
1419 else
1420 mnShowState = SW_SHOWNORMAL;
1422 else
1424 if ( IsIconic( mhWnd ) || IsZoomed( mhWnd ) )
1425 ShowWindow( mhWnd, SW_RESTORE );
1428 USHORT nEvent = 0;
1429 UINT nPosSize = 0;
1430 RECT aClientRect, aWindowRect;
1431 GetClientRect( mhWnd, &aClientRect ); // x,y always 0,0, but width and height without border
1432 GetWindowRect( mhWnd, &aWindowRect ); // x,y in screen coordinates, width and height with border
1434 if ( !(nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) )
1435 nPosSize |= SWP_NOMOVE;
1436 else
1438 //DBG_ASSERT( nX && nY, " Windowposition of (0,0) requested!" );
1439 nEvent = SALEVENT_MOVE;
1441 if ( !(nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) )
1442 nPosSize |= SWP_NOSIZE;
1443 else
1444 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
1446 if ( !(nFlags & SAL_FRAME_POSSIZE_X) )
1447 nX = aWindowRect.left;
1448 if ( !(nFlags & SAL_FRAME_POSSIZE_Y) )
1449 nY = aWindowRect.top;
1450 if ( !(nFlags & SAL_FRAME_POSSIZE_WIDTH) )
1451 nWidth = aClientRect.right-aClientRect.left;
1452 if ( !(nFlags & SAL_FRAME_POSSIZE_HEIGHT) )
1453 nHeight = aClientRect.bottom-aClientRect.top;
1455 // Calculate window size including the border
1456 RECT aWinRect;
1457 aWinRect.left = 0;
1458 aWinRect.right = (int)nWidth-1;
1459 aWinRect.top = 0;
1460 aWinRect.bottom = (int)nHeight-1;
1461 AdjustWindowRectEx( &aWinRect, GetWindowStyle( mhWnd ),
1462 FALSE, GetWindowExStyle( mhWnd ) );
1463 nWidth = aWinRect.right - aWinRect.left + 1;
1464 nHeight = aWinRect.bottom - aWinRect.top + 1;
1466 if ( !(nPosSize & SWP_NOMOVE) && ::GetParent( mhWnd ) )
1468 // --- RTL --- (mirror window pos)
1469 RECT aParentRect;
1470 GetClientRect( ImplGetParentHwnd( mhWnd ), &aParentRect );
1471 if( Application::GetSettings().GetLayoutRTL() )
1472 nX = (aParentRect.right - aParentRect.left) - nWidth-1 - nX;
1474 //#110386#, do not transform coordinates for system child windows
1475 if( !(GetWindowStyle( mhWnd ) & WS_CHILD) )
1477 POINT aPt;
1478 aPt.x = nX;
1479 aPt.y = nY;
1481 HWND parentHwnd = ImplGetParentHwnd( mhWnd );
1482 WinSalFrame* pParentFrame = GetWindowPtr( parentHwnd );
1483 if ( pParentFrame && pParentFrame->mnShowState == SW_SHOWMAXIMIZED )
1485 // #i42485#: parent will be shown maximized in which case
1486 // a ClientToScreen uses the wrong coordinates (i.e. those from the restore pos)
1487 // so use the (already updated) frame geometry for the transformation
1488 aPt.x += pParentFrame->maGeometry.nX;
1489 aPt.y += pParentFrame->maGeometry.nY;
1491 else
1492 ClientToScreen( parentHwnd, &aPt );
1494 nX = aPt.x;
1495 nY = aPt.y;
1499 // #i3338# to be conformant to UNIX we must position the client window, ie without the decoration
1500 // #i43250# if the position was read from the system (GetWindowRect(), see above), it must not be modified
1501 if ( nFlags & SAL_FRAME_POSSIZE_X )
1502 nX += aWinRect.left;
1503 if ( nFlags & SAL_FRAME_POSSIZE_Y )
1504 nY += aWinRect.top;
1506 int nScreenX;
1507 int nScreenY;
1508 int nScreenWidth;
1509 int nScreenHeight;
1512 RECT aRect;
1513 ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1514 nScreenX = aRect.left;
1515 nScreenY = aRect.top;
1516 nScreenWidth = aRect.right-aRect.left;
1517 nScreenHeight = aRect.bottom-aRect.top;
1519 if ( mbDefPos && (nPosSize & SWP_NOMOVE)) // we got no positioning request, so choose default position
1521 // center window
1523 HWND hWndParent = ::GetParent( mhWnd );
1524 // Search for TopLevel Frame
1525 while ( hWndParent && (GetWindowStyle( hWndParent ) & WS_CHILD) )
1526 hWndParent = ::GetParent( hWndParent );
1527 // if the Window has a Parent, than center the window to
1528 // the parent, in the other case to the screen
1529 if ( hWndParent && !IsIconic( hWndParent ) &&
1530 (GetWindowStyle( hWndParent ) & WS_VISIBLE) )
1532 RECT aParentRect;
1533 GetWindowRect( hWndParent, &aParentRect );
1534 int nParentWidth = aParentRect.right-aParentRect.left;
1535 int nParentHeight = aParentRect.bottom-aParentRect.top;
1537 // We don't center, when Parent is smaller than our window
1538 if ( (nParentWidth-GetSystemMetrics( SM_CXFIXEDFRAME ) <= nWidth) &&
1539 (nParentHeight-GetSystemMetrics( SM_CYFIXEDFRAME ) <= nHeight) )
1541 int nOff = GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
1542 nX = aParentRect.left+nOff;
1543 nY = aParentRect.top+nOff;
1545 else
1547 nX = (nParentWidth-nWidth)/2 + aParentRect.left;
1548 nY = (nParentHeight-nHeight)/2 + aParentRect.top;
1551 else
1553 POINT pt;
1554 GetCursorPos( &pt );
1555 RECT aRect;
1556 aRect.left = pt.x;
1557 aRect.top = pt.y;
1558 aRect.right = pt.x+2;
1559 aRect.bottom = pt.y+2;
1561 // dualmonitor support:
1562 // Get screensize of the monitor whith the mouse pointer
1563 ImplSalGetWorkArea( mhWnd, &aRect, &aRect );
1565 nX = ((aRect.right-aRect.left)-nWidth)/2 + aRect.left;
1566 nY = ((aRect.bottom-aRect.top)-nHeight)/2 + aRect.top;
1570 //if ( bVisible )
1571 // mbDefPos = FALSE;
1573 mbDefPos = FALSE; // center only once
1574 nPosSize &= ~SWP_NOMOVE; // activate positioning
1575 nEvent = SALEVENT_MOVERESIZE;
1579 // Adjust Window in the screen
1580 BOOL bCheckOffScreen = TRUE;
1582 // but don't do this for floaters or ownerdraw windows that are currently moved interactively
1583 if( (mnStyle & SAL_FRAME_STYLE_FLOAT) && !(mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
1584 bCheckOffScreen = FALSE;
1586 if( mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
1588 // may be the window is currently being moved (mouse is captured), then no check is required
1589 if( mhWnd == ::GetCapture() )
1590 bCheckOffScreen = FALSE;
1591 else
1592 bCheckOffScreen = TRUE;
1595 if( bCheckOffScreen )
1597 if ( nX+nWidth > nScreenX+nScreenWidth )
1598 nX = (nScreenX+nScreenWidth) - nWidth;
1599 if ( nY+nHeight > nScreenY+nScreenHeight )
1600 nY = (nScreenY+nScreenHeight) - nHeight;
1601 if ( nX < nScreenX )
1602 nX = nScreenX;
1603 if ( nY < nScreenY )
1604 nY = nScreenY;
1607 UINT nPosFlags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | nPosSize;
1608 // bring floating windows always to top
1609 if( !(mnStyle & SAL_FRAME_STYLE_FLOAT) )
1610 nPosFlags |= SWP_NOZORDER; // do not change z-order
1612 SetWindowPos( mhWnd, HWND_TOP, nX, nY, (int)nWidth, (int)nHeight, nPosFlags );
1614 UpdateFrameGeometry( mhWnd, this );
1616 // Notification -- really ???
1617 if( nEvent )
1618 CallCallback( nEvent, NULL );
1621 // -----------------------------------------------------------------------
1623 static void ImplSetParentFrame( WinSalFrame* pThis, HWND hNewParentWnd, BOOL bAsChild )
1625 // save hwnd, will be overwritten in WM_CREATE during createwindow
1626 HWND hWndOld = pThis->mhWnd;
1627 HWND hWndOldParent = ::GetParent( hWndOld );
1628 SalData* pSalData = GetSalData();
1630 if( hNewParentWnd == hWndOldParent )
1631 return;
1633 ::std::vector< WinSalFrame* > children;
1634 ::std::vector< WinSalObject* > systemChildren;
1636 // search child windows
1637 WinSalFrame *pFrame = pSalData->mpFirstFrame;
1638 while( pFrame )
1640 HWND hWndParent = ::GetParent( pFrame->mhWnd );
1641 if( pThis->mhWnd == hWndParent )
1642 children.push_back( pFrame );
1643 pFrame = pFrame->mpNextFrame;
1646 // search system child windows (plugins etc.)
1647 WinSalObject *pObject = pSalData->mpFirstObject;
1648 while( pObject )
1650 HWND hWndParent = ::GetParent( pObject->mhWnd );
1651 if( pThis->mhWnd == hWndParent )
1652 systemChildren.push_back( pObject );
1653 pObject = pObject->mpNextObject;
1656 BOOL bNeedGraphics = pThis->mbGraphics;
1657 BOOL bNeedCacheDC = FALSE;
1659 HFONT hFont = NULL;
1660 HPEN hPen = NULL;
1661 HBRUSH hBrush = NULL;
1663 #if OSL_DEBUG_LEVEL > 0
1664 int oldCount = pSalData->mnCacheDCInUse;
1665 (void)oldCount;
1666 #endif
1668 // Release Cache DC
1669 if ( pThis->mpGraphics2 &&
1670 pThis->mpGraphics2->mhDC )
1672 // save current gdi objects before hdc is gone
1673 hFont = (HFONT) GetCurrentObject( pThis->mpGraphics2->mhDC, OBJ_FONT);
1674 hPen = (HPEN) GetCurrentObject( pThis->mpGraphics2->mhDC, OBJ_PEN);
1675 hBrush = (HBRUSH) GetCurrentObject( pThis->mpGraphics2->mhDC, OBJ_BRUSH);
1676 pThis->ReleaseGraphics( pThis->mpGraphics2 );
1678 // recreate cache dc only if it was destroyed
1679 bNeedCacheDC = TRUE;
1682 // destroy saved DC
1683 if ( pThis->mpGraphics )
1685 if ( pThis->mpGraphics->mhDefPal )
1686 SelectPalette( pThis->mpGraphics->mhDC, pThis->mpGraphics->mhDefPal, TRUE );
1687 ImplSalDeInitGraphics( pThis->mpGraphics );
1688 ReleaseDC( pThis->mhWnd, pThis->mpGraphics->mhDC );
1691 // create a new hwnd with the same styles
1692 HWND hWndParent = hNewParentWnd;
1693 // forward to main thread
1694 HWND hWnd = (HWND) ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1695 bAsChild ? SAL_MSG_RECREATECHILDHWND : SAL_MSG_RECREATEHWND,
1696 (WPARAM) hWndParent, (LPARAM)pThis->mhWnd );
1698 // succeeded ?
1699 DBG_ASSERT( IsWindow( hWnd ), "WinSalFrame::SetParent not successful");
1701 // recreate DCs
1702 if( bNeedGraphics )
1704 if( pThis->mpGraphics2 )
1706 pThis->mpGraphics2->mhWnd = hWnd;
1708 if( bNeedCacheDC )
1710 // re-create cached DC
1711 HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1712 SAL_MSG_GETDC,
1713 (WPARAM) hWnd, 0 );
1714 if ( hDC )
1716 pThis->mpGraphics2->mhDC = hDC;
1717 if ( pSalData->mhDitherPal )
1719 pThis->mpGraphics2->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1720 RealizePalette( hDC );
1722 ImplSalInitGraphics( pThis->mpGraphics2 );
1724 // re-select saved gdi objects
1725 if( hFont )
1726 SelectObject( hDC, hFont );
1727 if( hPen )
1728 SelectObject( hDC, hPen );
1729 if( hBrush )
1730 SelectObject( hDC, hBrush );
1732 pThis->mbGraphics = TRUE;
1734 pSalData->mnCacheDCInUse++;
1736 DBG_ASSERT( oldCount == pSalData->mnCacheDCInUse, "WinSalFrame::SetParent() hDC count corrupted");
1741 if( pThis->mpGraphics )
1743 // re-create DC
1744 pThis->mpGraphics->mhWnd = hWnd;
1745 pThis->mpGraphics->mhDC = GetDC( hWnd );
1746 if ( GetSalData()->mhDitherPal )
1748 pThis->mpGraphics->mhDefPal = SelectPalette( pThis->mpGraphics->mhDC, GetSalData()->mhDitherPal, TRUE );
1749 RealizePalette( pThis->mpGraphics->mhDC );
1751 ImplSalInitGraphics( pThis->mpGraphics );
1752 pThis->mbGraphics = TRUE;
1757 // TODO: add SetParent() call for SalObjects
1758 DBG_ASSERT( systemChildren.empty(), "WinSalFrame::SetParent() parent of living system child window will be destroyed!");
1760 // reparent children before old parent is destroyed
1761 for( ::std::vector< WinSalFrame* >::iterator iChild = children.begin(); iChild != children.end(); iChild++ )
1762 ImplSetParentFrame( *iChild, hWnd, FALSE );
1764 children.clear();
1765 systemChildren.clear();
1767 // Now destroy original HWND in the thread where it was created.
1768 ImplSendMessage( GetSalData()->mpFirstInstance->mhComWnd,
1769 SAL_MSG_DESTROYHWND, (WPARAM) 0, (LPARAM)hWndOld);
1772 // -----------------------------------------------------------------------
1774 void WinSalFrame::SetParent( SalFrame* pNewParent )
1776 WinSalFrame::mbInReparent = TRUE;
1777 ImplSetParentFrame( this, static_cast<WinSalFrame*>(pNewParent)->mhWnd, FALSE );
1778 WinSalFrame::mbInReparent = FALSE;
1781 bool WinSalFrame::SetPluginParent( SystemParentData* pNewParent )
1783 if ( pNewParent->hWnd == 0 )
1785 pNewParent->hWnd = GetDesktopWindow();
1788 WinSalFrame::mbInReparent = TRUE;
1789 ImplSetParentFrame( this, pNewParent->hWnd, TRUE );
1790 WinSalFrame::mbInReparent = FALSE;
1791 return true;
1795 // -----------------------------------------------------------------------
1797 void WinSalFrame::GetWorkArea( Rectangle &rRect )
1799 RECT aRect;
1800 ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1801 rRect.nLeft = aRect.left;
1802 rRect.nRight = aRect.right-1;
1803 rRect.nTop = aRect.top;
1804 rRect.nBottom = aRect.bottom-1;
1807 // -----------------------------------------------------------------------
1809 void WinSalFrame::GetClientSize( long& rWidth, long& rHeight )
1811 rWidth = maGeometry.nWidth;
1812 rHeight = maGeometry.nHeight;
1815 // -----------------------------------------------------------------------
1817 void WinSalFrame::SetWindowState( const SalFrameState* pState )
1819 // Wir testen, ob das Fenster ueberhaupt auf den Bildschirm passt, damit
1820 // nicht wenn die Bildschirm-Aufloesung geaendert wurde, das Fenster aus
1821 // diesem herausragt
1822 int nX;
1823 int nY;
1824 int nWidth;
1825 int nHeight;
1826 int nScreenX;
1827 int nScreenY;
1828 int nScreenWidth;
1829 int nScreenHeight;
1831 RECT aRect;
1832 ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1833 // #102500# allow some overlap, the window could have been made a little larger than the physical screen
1834 nScreenX = aRect.left-10;
1835 nScreenY = aRect.top-10;
1836 nScreenWidth = aRect.right-aRect.left+20;
1837 nScreenHeight = aRect.bottom-aRect.top+20;
1839 UINT nPosSize = 0;
1840 RECT aWinRect;
1841 GetWindowRect( mhWnd, &aWinRect );
1843 // to be consistent with Unix, the frame state is without(!) decoration
1844 // ->add the decoration
1845 RECT aRect2 = aWinRect;
1846 AdjustWindowRectEx( &aRect2, GetWindowStyle( mhWnd ),
1847 FALSE, GetWindowExStyle( mhWnd ) );
1848 long nTopDeco = abs( aWinRect.top - aRect2.top );
1849 long nLeftDeco = abs( aWinRect.left - aRect2.left );
1850 long nBottomDeco = abs( aWinRect.bottom - aRect2.bottom );
1851 long nRightDeco = abs( aWinRect.right - aRect2.right );
1853 // Fenster-Position/Groesse in den Bildschirm einpassen
1854 if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y)) )
1855 nPosSize |= SWP_NOMOVE;
1856 if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)) )
1857 nPosSize |= SWP_NOSIZE;
1858 if ( pState->mnMask & SAL_FRAMESTATE_MASK_X )
1859 nX = (int)pState->mnX - nLeftDeco;
1860 else
1861 nX = aWinRect.left;
1862 if ( pState->mnMask & SAL_FRAMESTATE_MASK_Y )
1863 nY = (int)pState->mnY - nTopDeco;
1864 else
1865 nY = aWinRect.top;
1866 if ( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH )
1867 nWidth = (int)pState->mnWidth + nLeftDeco + nRightDeco;
1868 else
1869 nWidth = aWinRect.right-aWinRect.left;
1870 if ( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT )
1871 nHeight = (int)pState->mnHeight + nTopDeco + nBottomDeco;
1872 else
1873 nHeight = aWinRect.bottom-aWinRect.top;
1875 // Adjust Window in the screen:
1876 // if it does not fit into the screen do nothing, ie default pos/size will be used
1877 // if there is an overlap with the screen border move the window while keeping its size
1879 if( nWidth > nScreenWidth || nHeight > nScreenHeight )
1880 nPosSize |= (SWP_NOMOVE | SWP_NOSIZE);
1882 if ( nX+nWidth > nScreenX+nScreenWidth )
1883 nX = (nScreenX+nScreenWidth) - nWidth;
1884 if ( nY+nHeight > nScreenY+nScreenHeight )
1885 nY = (nScreenY+nScreenHeight) - nHeight;
1886 if ( nX < nScreenX )
1887 nX = nScreenX;
1888 if ( nY < nScreenY )
1889 nY = nScreenY;
1891 // Restore-Position setzen
1892 WINDOWPLACEMENT aPlacement;
1893 aPlacement.length = sizeof( aPlacement );
1894 GetWindowPlacement( mhWnd, &aPlacement );
1896 // Status setzen
1897 BOOL bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
1898 BOOL bUpdateHiddenFramePos = FALSE;
1899 if ( !bVisible )
1901 aPlacement.showCmd = SW_HIDE;
1903 if ( mbOverwriteState )
1905 if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
1907 if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
1908 mnShowState = SW_SHOWMINIMIZED;
1909 else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1911 mnShowState = SW_SHOWMAXIMIZED;
1912 bUpdateHiddenFramePos = TRUE;
1914 else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
1915 mnShowState = SW_SHOWNORMAL;
1919 else
1921 if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
1923 if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
1925 if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1926 aPlacement.flags |= WPF_RESTORETOMAXIMIZED;
1927 aPlacement.showCmd = SW_SHOWMINIMIZED;
1929 else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1930 aPlacement.showCmd = SW_SHOWMAXIMIZED;
1931 else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
1932 aPlacement.showCmd = SW_RESTORE;
1936 // Wenn Fenster nicht minimiert/maximiert ist oder nicht optisch
1937 // umgesetzt werden muss, dann SetWindowPos() benutzen, da
1938 // SetWindowPlacement() die TaskBar mit einrechnet
1939 if ( !IsIconic( mhWnd ) && !IsZoomed( mhWnd ) &&
1940 (!bVisible || (aPlacement.showCmd == SW_RESTORE)) )
1942 if( bUpdateHiddenFramePos )
1944 // #96084 set a useful internal window size because
1945 // the window will not be maximized (and the size updated) before show()
1946 SetMaximizedFrameGeometry( mhWnd, this );
1948 else
1949 SetWindowPos( mhWnd, 0,
1950 nX, nY, nWidth, nHeight,
1951 SWP_NOZORDER | SWP_NOACTIVATE | nPosSize );
1953 else
1955 if( !(nPosSize & (SWP_NOMOVE|SWP_NOSIZE)) )
1957 aPlacement.rcNormalPosition.left = nX-nScreenX;
1958 aPlacement.rcNormalPosition.top = nY-nScreenY;
1959 aPlacement.rcNormalPosition.right = nX+nWidth-nScreenX;
1960 aPlacement.rcNormalPosition.bottom = nY+nHeight-nScreenY;
1962 SetWindowPlacement( mhWnd, &aPlacement );
1965 if( !(nPosSize & SWP_NOMOVE) )
1966 mbDefPos = FALSE; // window was positioned
1969 // -----------------------------------------------------------------------
1971 BOOL WinSalFrame::GetWindowState( SalFrameState* pState )
1973 if ( maState.mnWidth && maState.mnHeight )
1975 *pState = maState;
1976 // #94144# allow Minimize again, should be masked out when read from configuration
1977 // 91625 - Don't save minimize
1978 //if ( !(pState->mnState & SAL_FRAMESTATE_MAXIMIZED) )
1979 if ( !(pState->mnState & (SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED)) )
1980 pState->mnState |= SAL_FRAMESTATE_NORMAL;
1981 return TRUE;
1984 return FALSE;
1987 // -----------------------------------------------------------------------
1989 void WinSalFrame::SetScreenNumber( unsigned int nNewScreen )
1991 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
1992 if( pSys )
1994 const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
1995 pSys->getMonitors();
1996 size_t nMon = rMonitors.size();
1997 if( nNewScreen < nMon )
1999 Point aOldMonPos, aNewMonPos( rMonitors[nNewScreen].m_aArea.TopLeft() );
2000 Point aCurPos( maGeometry.nX, maGeometry.nY );
2001 for( size_t i = 0; i < nMon; i++ )
2003 if( rMonitors[i].m_aArea.IsInside( aCurPos ) )
2005 aOldMonPos = rMonitors[i].m_aArea.TopLeft();
2006 break;
2009 mnDisplay = nNewScreen;
2010 maGeometry.nScreenNumber = nNewScreen;
2011 SetPosSize( aNewMonPos.X() + (maGeometry.nX - aOldMonPos.X()),
2012 aNewMonPos.Y() + (maGeometry.nY - aOldMonPos.Y()),
2013 0, 0,
2014 SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
2019 // -----------------------------------------------------------------------
2021 void WinSalFrame::ShowFullScreen( BOOL bFullScreen, sal_Int32 nDisplay )
2023 if ( (mbFullScreen == bFullScreen) && (!bFullScreen || (mnDisplay == nDisplay)) )
2024 return;
2026 mbFullScreen = bFullScreen;
2027 mnDisplay = nDisplay;
2029 if ( bFullScreen )
2031 // Damit Taskleiste von Windows ausgeblendet wird
2032 DWORD nExStyle = GetWindowExStyle( mhWnd );
2033 if ( nExStyle & WS_EX_TOOLWINDOW )
2035 mbFullScreenToolWin = TRUE;
2036 nExStyle &= ~WS_EX_TOOLWINDOW;
2037 SetWindowExStyle( mhWnd, nExStyle );
2039 // save old position
2040 GetWindowRect( mhWnd, &maFullScreenRect );
2042 // save show state
2043 mnFullScreenShowState = mnShowState;
2044 if ( !(GetWindowStyle( mhWnd ) & WS_VISIBLE) )
2045 mnShowState = SW_SHOW;
2047 // set window to screen size
2048 ImplSalFrameFullScreenPos( this, TRUE );
2050 else
2052 // wenn ShowState wieder hergestellt werden muss, hiden wir zuerst
2053 // das Fenster, damit es nicht so sehr flackert
2054 BOOL bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
2055 if ( bVisible && (mnShowState != mnFullScreenShowState) )
2056 ShowWindow( mhWnd, SW_HIDE );
2058 if ( mbFullScreenToolWin )
2059 SetWindowExStyle( mhWnd, GetWindowExStyle( mhWnd ) | WS_EX_TOOLWINDOW );
2060 mbFullScreenToolWin = FALSE;
2062 SetWindowPos( mhWnd, 0,
2063 maFullScreenRect.left,
2064 maFullScreenRect.top,
2065 maFullScreenRect.right-maFullScreenRect.left,
2066 maFullScreenRect.bottom-maFullScreenRect.top,
2067 SWP_NOZORDER | SWP_NOACTIVATE );
2069 // restore show state
2070 if ( mnShowState != mnFullScreenShowState )
2072 mnShowState = mnFullScreenShowState;
2073 if ( bVisible )
2075 mbInShow = TRUE;
2076 ShowWindow( mhWnd, mnShowState );
2077 mbInShow = FALSE;
2078 UpdateWindow( mhWnd );
2084 // -----------------------------------------------------------------------
2086 void WinSalFrame::StartPresentation( BOOL bStart )
2088 if ( mbPresentation == bStart )
2089 return;
2091 mbPresentation = bStart;
2093 SalData* pSalData = GetSalData();
2094 if ( bStart )
2096 if ( !pSalData->mpSageEnableProc )
2098 if ( pSalData->mnSageStatus != DISABLE_AGENT )
2100 OFSTRUCT aOS;
2101 OpenFile( "SAGE.DLL", &aOS, OF_EXIST );
2103 if ( !aOS.nErrCode )
2105 OUString aLibraryName( OUString::createFromAscii( aOS.szPathName ) );
2106 oslModule mhSageInst = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
2107 pSalData->mpSageEnableProc = (SysAgt_Enable_PROC)osl_getAsciiFunctionSymbol( mhSageInst, "System_Agent_Enable" );
2109 else
2110 pSalData->mnSageStatus = DISABLE_AGENT;
2114 if ( pSalData->mpSageEnableProc )
2116 pSalData->mnSageStatus = pSalData->mpSageEnableProc( GET_AGENT_STATUS );
2117 if ( pSalData->mnSageStatus == ENABLE_AGENT )
2118 pSalData->mpSageEnableProc( DISABLE_AGENT );
2121 // Bildschirmschoner ausschalten, wenn Praesentation laueft
2122 SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0,
2123 &(pSalData->mbScrSvrEnabled), 0 );
2124 if ( pSalData->mbScrSvrEnabled )
2125 SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, FALSE, 0, 0 );
2127 else
2129 // Bildschirmschoner wieder einschalten
2130 if ( pSalData->mbScrSvrEnabled )
2131 SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, pSalData->mbScrSvrEnabled, 0, 0 );
2133 // Systemagenten wieder aktivieren
2134 if ( pSalData->mnSageStatus == ENABLE_AGENT )
2135 pSalData->mpSageEnableProc( pSalData->mnSageStatus );
2139 // -----------------------------------------------------------------------
2141 void WinSalFrame::SetAlwaysOnTop( BOOL bOnTop )
2143 HWND hWnd;
2144 if ( bOnTop )
2145 hWnd = HWND_TOPMOST;
2146 else
2147 hWnd = HWND_NOTOPMOST;
2148 SetWindowPos( mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
2151 // -----------------------------------------------------------------------
2153 static void ImplSalToTop( HWND hWnd, USHORT nFlags )
2155 WinSalFrame* pToTopFrame = GetWindowPtr( hWnd );
2156 if( pToTopFrame && (pToTopFrame->mnStyle & SAL_FRAME_STYLE_SYSTEMCHILD) != 0 )
2157 BringWindowToTop( hWnd );
2159 if ( nFlags & SAL_FRAME_TOTOP_FOREGROUNDTASK )
2160 SetForegroundWindow( hWnd );
2162 if ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
2164 HWND hIconicWnd = hWnd;
2165 while ( hIconicWnd )
2167 if ( IsIconic( hIconicWnd ) )
2169 WinSalFrame* pFrame = GetWindowPtr( hIconicWnd );
2170 if ( pFrame )
2172 if ( GetWindowPtr( hWnd )->mbRestoreMaximize )
2173 ShowWindow( hIconicWnd, SW_MAXIMIZE );
2174 else
2175 ShowWindow( hIconicWnd, SW_RESTORE );
2177 else
2178 ShowWindow( hIconicWnd, SW_RESTORE );
2181 hIconicWnd = ::GetParent( hIconicWnd );
2185 if ( !IsIconic( hWnd ) && IsWindowVisible( hWnd ) )
2187 SetFocus( hWnd );
2189 // Windows behauptet oefters mal, das man den Focus hat, obwohl
2190 // man diesen nicht hat. Wenn dies der Fall ist, dann versuchen
2191 // wir diesen auch ganz richtig zu bekommen.
2192 if ( ::GetFocus() == hWnd )
2193 SetForegroundWindow( hWnd );
2197 // -----------------------------------------------------------------------
2199 void WinSalFrame::ToTop( USHORT nFlags )
2201 nFlags &= ~SAL_FRAME_TOTOP_GRABFOCUS; // this flag is not needed on win32
2202 // Post this Message to the window, because this only works
2203 // in the thread of the window, which has create this window.
2204 // We post this message to avoid deadlocks
2205 if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
2206 ImplPostMessage( mhWnd, SAL_MSG_TOTOP, nFlags, 0 );
2207 else
2208 ImplSalToTop( mhWnd, nFlags );
2211 // -----------------------------------------------------------------------
2213 void WinSalFrame::SetPointer( PointerStyle ePointerStyle )
2215 struct ImplPtrData
2217 HCURSOR mhCursor;
2218 LPCSTR mnSysId;
2219 UINT mnOwnId;
2222 static ImplPtrData aImplPtrTab[POINTER_COUNT] =
2224 { 0, IDC_ARROW, 0 }, // POINTER_ARROW
2225 { 0, 0, SAL_RESID_POINTER_NULL }, // POINTER_NULL
2226 { 0, IDC_WAIT, 0 }, // POINTER_WAIT
2227 { 0, IDC_IBEAM, 0 }, // POINTER_TEXT
2228 { 0, IDC_HELP, 0 }, // POINTER_HELP
2229 { 0, 0, SAL_RESID_POINTER_CROSS }, // POINTER_CROSS
2230 { 0, 0, SAL_RESID_POINTER_MOVE }, // POINTER_MOVE
2231 { 0, IDC_SIZENS, 0 }, // POINTER_NSIZE
2232 { 0, IDC_SIZENS, 0 }, // POINTER_SSIZE
2233 { 0, IDC_SIZEWE, 0 }, // POINTER_WSIZE
2234 { 0, IDC_SIZEWE, 0 }, // POINTER_ESIZE
2235 { 0, IDC_SIZENWSE, 0 }, // POINTER_NWSIZE
2236 { 0, IDC_SIZENESW, 0 }, // POINTER_NESIZE
2237 { 0, IDC_SIZENESW, 0 }, // POINTER_SWSIZE
2238 { 0, IDC_SIZENWSE, 0 }, // POINTER_SESIZE
2239 { 0, IDC_SIZENS, 0 }, // POINTER_WINDOW_NSIZE
2240 { 0, IDC_SIZENS, 0 }, // POINTER_WINDOW_SSIZE
2241 { 0, IDC_SIZEWE, 0 }, // POINTER_WINDOW_WSIZE
2242 { 0, IDC_SIZEWE, 0 }, // POINTER_WINDOW_ESIZE
2243 { 0, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_NWSIZE
2244 { 0, IDC_SIZENESW, 0 }, // POINTER_WINDOW_NESIZE
2245 { 0, IDC_SIZENESW, 0 }, // POINTER_WINDOW_SWSIZE
2246 { 0, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_SESIZE
2247 { 0, 0, SAL_RESID_POINTER_HSPLIT }, // POINTER_HSPLIT
2248 { 0, 0, SAL_RESID_POINTER_VSPLIT }, // POINTER_VSPLIT
2249 { 0, 0, SAL_RESID_POINTER_HSIZEBAR }, // POINTER_HSIZEBAR
2250 { 0, 0, SAL_RESID_POINTER_VSIZEBAR }, // POINTER_VSIZEBAR
2251 { 0, 0, SAL_RESID_POINTER_HAND }, // POINTER_HAND
2252 { 0, 0, SAL_RESID_POINTER_REFHAND }, // POINTER_REFHAND
2253 { 0, 0, SAL_RESID_POINTER_PEN }, // POINTER_PEN
2254 { 0, 0, SAL_RESID_POINTER_MAGNIFY }, // POINTER_MAGNIFY
2255 { 0, 0, SAL_RESID_POINTER_FILL }, // POINTER_FILL
2256 { 0, 0, SAL_RESID_POINTER_ROTATE }, // POINTER_ROTATE
2257 { 0, 0, SAL_RESID_POINTER_HSHEAR }, // POINTER_HSHEAR
2258 { 0, 0, SAL_RESID_POINTER_VSHEAR }, // POINTER_VSHEAR
2259 { 0, 0, SAL_RESID_POINTER_MIRROR }, // POINTER_MIRROR
2260 { 0, 0, SAL_RESID_POINTER_CROOK }, // POINTER_CROOK
2261 { 0, 0, SAL_RESID_POINTER_CROP }, // POINTER_CROP
2262 { 0, 0, SAL_RESID_POINTER_MOVEPOINT }, // POINTER_MOVEPOINT
2263 { 0, 0, SAL_RESID_POINTER_MOVEBEZIERWEIGHT }, // POINTER_MOVEBEZIERWEIGHT
2264 { 0, 0, SAL_RESID_POINTER_MOVEDATA }, // POINTER_MOVEDATA
2265 { 0, 0, SAL_RESID_POINTER_COPYDATA }, // POINTER_COPYDATA
2266 { 0, 0, SAL_RESID_POINTER_LINKDATA }, // POINTER_LINKDATA
2267 { 0, 0, SAL_RESID_POINTER_MOVEDATALINK }, // POINTER_MOVEDATALINK
2268 { 0, 0, SAL_RESID_POINTER_COPYDATALINK }, // POINTER_COPYDATALINK
2269 { 0, 0, SAL_RESID_POINTER_MOVEFILE }, // POINTER_MOVEFILE
2270 { 0, 0, SAL_RESID_POINTER_COPYFILE }, // POINTER_COPYFILE
2271 { 0, 0, SAL_RESID_POINTER_LINKFILE }, // POINTER_LINKFILE
2272 { 0, 0, SAL_RESID_POINTER_MOVEFILELINK }, // POINTER_MOVEFILELINK
2273 { 0, 0, SAL_RESID_POINTER_COPYFILELINK }, // POINTER_COPYFILELINK
2274 { 0, 0, SAL_RESID_POINTER_MOVEFILES }, // POINTER_MOVEFILES
2275 { 0, 0, SAL_RESID_POINTER_COPYFILES }, // POINTER_COPYFILES
2276 { 0, 0, SAL_RESID_POINTER_NOTALLOWED }, // POINTER_NOTALLOWED
2277 { 0, 0, SAL_RESID_POINTER_DRAW_LINE }, // POINTER_DRAW_LINE
2278 { 0, 0, SAL_RESID_POINTER_DRAW_RECT }, // POINTER_DRAW_RECT
2279 { 0, 0, SAL_RESID_POINTER_DRAW_POLYGON }, // POINTER_DRAW_POLYGON
2280 { 0, 0, SAL_RESID_POINTER_DRAW_BEZIER }, // POINTER_DRAW_BEZIER
2281 { 0, 0, SAL_RESID_POINTER_DRAW_ARC }, // POINTER_DRAW_ARC
2282 { 0, 0, SAL_RESID_POINTER_DRAW_PIE }, // POINTER_DRAW_PIE
2283 { 0, 0, SAL_RESID_POINTER_DRAW_CIRCLECUT }, // POINTER_DRAW_CIRCLECUT
2284 { 0, 0, SAL_RESID_POINTER_DRAW_ELLIPSE }, // POINTER_DRAW_ELLIPSE
2285 { 0, 0, SAL_RESID_POINTER_DRAW_FREEHAND }, // POINTER_DRAW_FREEHAND
2286 { 0, 0, SAL_RESID_POINTER_DRAW_CONNECT }, // POINTER_DRAW_CONNECT
2287 { 0, 0, SAL_RESID_POINTER_DRAW_TEXT }, // POINTER_DRAW_TEXT
2288 { 0, 0, SAL_RESID_POINTER_DRAW_CAPTION }, // POINTER_DRAW_CAPTION
2289 { 0, 0, SAL_RESID_POINTER_CHART }, // POINTER_CHART
2290 { 0, 0, SAL_RESID_POINTER_DETECTIVE }, // POINTER_DETECTIVE
2291 { 0, 0, SAL_RESID_POINTER_PIVOT_COL }, // POINTER_PIVOT_COL
2292 { 0, 0, SAL_RESID_POINTER_PIVOT_ROW }, // POINTER_PIVOT_ROW
2293 { 0, 0, SAL_RESID_POINTER_PIVOT_FIELD }, // POINTER_PIVOT_FIELD
2294 { 0, 0, SAL_RESID_POINTER_CHAIN }, // POINTER_CHAIN
2295 { 0, 0, SAL_RESID_POINTER_CHAIN_NOTALLOWED }, // POINTER_CHAIN_NOTALLOWED
2296 { 0, 0, SAL_RESID_POINTER_TIMEEVENT_MOVE }, // POINTER_TIMEEVENT_MOVE
2297 { 0, 0, SAL_RESID_POINTER_TIMEEVENT_SIZE }, // POINTER_TIMEEVENT_SIZE
2298 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_N }, // POINTER_AUTOSCROLL_N
2299 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_S }, // POINTER_AUTOSCROLL_S
2300 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_W }, // POINTER_AUTOSCROLL_W
2301 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_E }, // POINTER_AUTOSCROLL_E
2302 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NW }, // POINTER_AUTOSCROLL_NW
2303 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NE }, // POINTER_AUTOSCROLL_NE
2304 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SW }, // POINTER_AUTOSCROLL_SW
2305 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SE }, // POINTER_AUTOSCROLL_SE
2306 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NS }, // POINTER_AUTOSCROLL_NS
2307 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_WE }, // POINTER_AUTOSCROLL_WE
2308 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NSWE }, // POINTER_AUTOSCROLL_NSWE
2309 { 0, 0, SAL_RESID_POINTER_AIRBRUSH }, // POINTER_AIRBRUSH
2310 { 0, 0, SAL_RESID_POINTER_TEXT_VERTICAL }, // POINTER_TEXT_VERTICAL
2311 { 0, 0, SAL_RESID_POINTER_PIVOT_DELETE }, // POINTER_PIVOT_DELETE
2313 // --> FME 2004-07-30 #i32329# Enhanced table selection
2314 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_S }, // POINTER_TAB_SELECT_S
2315 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_E }, // POINTER_TAB_SELECT_E
2316 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SE }, // POINTER_TAB_SELECT_SE
2317 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_W }, // POINTER_TAB_SELECT_W
2318 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SW }, // POINTER_TAB_SELECT_SW
2319 // <--
2321 // --> FME 2004-08-16 #i20119# Paintbrush tool
2322 { 0, 0, SAL_RESID_POINTER_PAINTBRUSH } // POINTER_PAINTBRUSH
2323 // <--
2327 #if POINTER_COUNT != 94
2328 #error New Pointer must be defined!
2329 #endif
2331 // Mousepointer loaded ?
2332 if ( !aImplPtrTab[ePointerStyle].mhCursor )
2334 if ( aImplPtrTab[ePointerStyle].mnOwnId )
2335 aImplPtrTab[ePointerStyle].mhCursor = ImplLoadSalCursor( aImplPtrTab[ePointerStyle].mnOwnId );
2336 else
2337 aImplPtrTab[ePointerStyle].mhCursor = LoadCursor( 0, aImplPtrTab[ePointerStyle].mnSysId );
2340 // Unterscheidet sich der Mauspointer, dann den neuen setzen
2341 if ( mhCursor != aImplPtrTab[ePointerStyle].mhCursor )
2343 mhCursor = aImplPtrTab[ePointerStyle].mhCursor;
2344 SetCursor( mhCursor );
2348 // -----------------------------------------------------------------------
2350 void WinSalFrame::CaptureMouse( BOOL bCapture )
2352 // Send this Message to the window, because CaptureMouse() only work
2353 // in the thread of the window, which has create this window
2354 int nMsg;
2355 if ( bCapture )
2356 nMsg = SAL_MSG_CAPTUREMOUSE;
2357 else
2358 nMsg = SAL_MSG_RELEASEMOUSE;
2359 ImplSendMessage( mhWnd, nMsg, 0, 0 );
2362 // -----------------------------------------------------------------------
2364 void WinSalFrame::SetPointerPos( long nX, long nY )
2366 POINT aPt;
2367 aPt.x = (int)nX;
2368 aPt.y = (int)nY;
2369 ClientToScreen( mhWnd, &aPt );
2370 SetCursorPos( aPt.x, aPt.y );
2373 // -----------------------------------------------------------------------
2375 void WinSalFrame::Flush()
2377 GdiFlush();
2380 // -----------------------------------------------------------------------
2382 void WinSalFrame::Sync()
2384 GdiFlush();
2387 // -----------------------------------------------------------------------
2389 static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pContext )
2391 WinSalFrame* pFrame = GetWindowPtr( hWnd );
2392 BOOL bIME = (pContext->mnOptions & SAL_INPUTCONTEXT_TEXT) != 0;
2393 if ( bIME )
2395 if ( !pFrame->mbIME )
2397 pFrame->mbIME = TRUE;
2399 if ( pFrame->mhDefIMEContext )
2401 ImmAssociateContext( pFrame->mhWnd, pFrame->mhDefIMEContext );
2402 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
2403 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
2404 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
2405 pFrame->mbHandleIME = !pFrame->mbSpezIME;
2409 // When the application can't handle IME messages, then the
2410 // System should handle the IME handling
2411 if ( !(pContext->mnOptions & SAL_INPUTCONTEXT_EXTTEXTINPUT) )
2412 pFrame->mbHandleIME = FALSE;
2414 // Set the Font for IME Handling
2415 if ( pContext->mpFont )
2417 HIMC hIMC = ImmGetContext( pFrame->mhWnd );
2418 if ( hIMC )
2420 LOGFONTW aLogFont;
2421 HDC hDC = GetDC( pFrame->mhWnd );
2422 // In case of vertical writing, always append a '@' to the
2423 // Windows font name, not only if such a Windows font really is
2424 // available (bTestVerticalAvail == false in the below call):
2425 // The Windows IME's candidates window seems to always use a
2426 // font that has all necessary glyphs, not necessarily the one
2427 // specified by this font name; but it seems to decide whether
2428 // to use that font's horizontal or vertical variant based on a
2429 // '@' in front of this font name.
2430 ImplGetLogFontFromFontSelect( hDC, pContext->mpFont, aLogFont,
2431 false );
2432 ReleaseDC( pFrame->mhWnd, hDC );
2433 ImmSetCompositionFontW( hIMC, &aLogFont );
2434 ImmReleaseContext( pFrame->mhWnd, hIMC );
2438 else
2440 if ( pFrame->mbIME )
2442 pFrame->mbIME = FALSE;
2443 pFrame->mbHandleIME = FALSE;
2444 ImmAssociateContext( pFrame->mhWnd, 0 );
2449 // -----------------------------------------------------------------------
2451 void WinSalFrame::SetInputContext( SalInputContext* pContext )
2453 // Must be called in the main thread!
2454 ImplSendMessage( mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, (LPARAM)(void*)pContext );
2457 // -----------------------------------------------------------------------
2459 static void ImplSalFrameEndExtTextInput( HWND hWnd, USHORT nFlags )
2461 HIMC hIMC = ImmGetContext( hWnd );
2462 if ( hIMC )
2464 DWORD nIndex;
2465 if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE )
2466 nIndex = CPS_COMPLETE;
2467 else
2468 nIndex = CPS_CANCEL;
2470 ImmNotifyIME( hIMC, NI_COMPOSITIONSTR, nIndex, 0 );
2471 ImmReleaseContext( hWnd, hIMC );
2475 // -----------------------------------------------------------------------
2477 void WinSalFrame::EndExtTextInput( USHORT nFlags )
2479 // Must be called in the main thread!
2480 ImplSendMessage( mhWnd, SAL_MSG_ENDEXTTEXTINPUT, (WPARAM)nFlags, 0 );
2483 // -----------------------------------------------------------------------
2485 static void ImplGetKeyNameText( LONG lParam, sal_Unicode* pBuf,
2486 UINT& rCount, UINT nMaxSize,
2487 const sal_Char* pReplace )
2489 DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::ImplGetKeyNameTextW(): WCHAR != sal_Unicode" );
2491 static const int nMaxKeyLen = 350;
2492 WCHAR aKeyBuf[ nMaxKeyLen ];
2493 int nKeyLen = 0;
2494 if ( lParam )
2496 if ( aSalShlData.mbWNT )
2498 nKeyLen = GetKeyNameTextW( lParam, aKeyBuf, nMaxKeyLen );
2499 // #i12401# the current unicows.dll has a bug in CharUpperBuffW, which corrupts the stack
2500 // fall back to the ANSI version instead
2501 DBG_ASSERT( nKeyLen <= nMaxKeyLen, "Invalid key name length!" );
2502 if( nKeyLen > nMaxKeyLen )
2503 nKeyLen = 0;
2504 else if( nKeyLen > 0 )
2506 // Capitalize just the first letter of key names
2507 CharLowerBuffW( aKeyBuf, nKeyLen );
2509 bool bUpper = true;
2510 for( WCHAR *pW=aKeyBuf, *pE=pW+nKeyLen; pW < pE; ++pW )
2512 if( bUpper )
2513 CharUpperBuffW( pW, 1 );
2514 bUpper = (*pW=='+') || (*pW=='-') || (*pW==' ') || (*pW=='.');
2518 else // !mbWnt
2520 sal_Char aAnsiKeyBuf[ nMaxKeyLen ];
2521 int nAnsiKeyLen = GetKeyNameTextA( lParam, aAnsiKeyBuf, nMaxKeyLen );
2522 DBG_ASSERT( nAnsiKeyLen <= nMaxKeyLen, "Invalid key name length!" );
2523 if( nAnsiKeyLen > nMaxKeyLen )
2524 nAnsiKeyLen = 0;
2525 else if( nAnsiKeyLen > 0 )
2527 // Capitalize just the first letter of key names
2528 // TODO: check MCBS key names
2529 CharLowerBuffA( aAnsiKeyBuf, nAnsiKeyLen );
2531 bool bUpper = true;
2532 for( sal_Char *pA=aAnsiKeyBuf, *pE=pA+nAnsiKeyLen; pA < pE; ++pA )
2534 if( bUpper )
2535 CharUpperBuffA( pA, 1 );
2536 bUpper = (*pA=='+') || (*pA=='-') || (*pA==' ') || (*pA=='.');
2539 // Convert to Unicode and copy the data in the Unicode Buffer
2540 nKeyLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED,
2541 aAnsiKeyBuf, nAnsiKeyLen, aKeyBuf, nMaxKeyLen );
2546 if ( (nKeyLen > 0) || pReplace )
2548 if( (rCount > 0) && (rCount < nMaxSize) )
2550 pBuf[rCount] = '+';
2551 rCount++;
2554 if( nKeyLen > 0 )
2556 if( nKeyLen + rCount > nMaxSize )
2557 nKeyLen = nMaxSize - rCount;
2558 memcpy( pBuf+rCount, aKeyBuf, nKeyLen*sizeof( sal_Unicode ) );
2559 rCount += nKeyLen;
2561 else // fall back to provided default name
2563 while( *pReplace && (rCount < nMaxSize) )
2565 pBuf[rCount] = *pReplace;
2566 rCount++;
2567 pReplace++;
2571 else
2572 rCount = 0;
2575 // -----------------------------------------------------------------------
2577 XubString WinSalFrame::GetKeyName( USHORT nKeyCode )
2579 static const int nMaxKeyLen = 350;
2580 sal_Unicode aKeyBuf[ nMaxKeyLen ];
2581 UINT nKeyBufLen = 0;
2582 UINT nSysCode = 0;
2584 if ( nKeyCode & KEY_MOD1 )
2586 nSysCode = MapVirtualKey( VK_CONTROL, 0 );
2587 nSysCode = (nSysCode << 16) | (((ULONG)1) << 25);
2588 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Ctrl" );
2591 if ( nKeyCode & KEY_MOD2 )
2593 nSysCode = MapVirtualKey( VK_MENU, 0 );
2594 nSysCode = (nSysCode << 16) | (((ULONG)1) << 25);
2595 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Alt" );
2598 if ( nKeyCode & KEY_SHIFT )
2600 nSysCode = MapVirtualKey( VK_SHIFT, 0 );
2601 nSysCode = (nSysCode << 16) | (((ULONG)1) << 25);
2602 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Shift" );
2605 USHORT nCode = nKeyCode & 0x0FFF;
2606 ULONG nSysCode2 = 0;
2607 sal_Char* pReplace = NULL;
2608 sal_Unicode cSVCode = 0;
2609 sal_Char aFBuf[4];
2610 nSysCode = 0;
2612 if ( (nCode >= KEY_0) && (nCode <= KEY_9) )
2613 cSVCode = '0' + (nCode - KEY_0);
2614 else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) )
2615 cSVCode = 'A' + (nCode - KEY_A);
2616 else if ( (nCode >= KEY_F1) && (nCode <= KEY_F26) )
2618 nSysCode = VK_F1 + (nCode - KEY_F1);
2619 aFBuf[0] = 'F';
2620 if ( (nCode >= KEY_F1) && (nCode <= KEY_F9) )
2622 aFBuf[1] = sal::static_int_cast<sal_Char>('1' + (nCode - KEY_F1));
2623 aFBuf[2] = 0;
2625 else if ( (nCode >= KEY_F10) && (nCode <= KEY_F19) )
2627 aFBuf[1] = '1';
2628 aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F10));
2629 aFBuf[3] = 0;
2631 else
2633 aFBuf[1] = '2';
2634 aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F20));
2635 aFBuf[3] = 0;
2637 pReplace = aFBuf;
2639 else
2641 switch ( nCode )
2643 case KEY_DOWN:
2644 nSysCode = VK_DOWN;
2645 nSysCode2 = (((ULONG)1) << 24);
2646 pReplace = "Down";
2647 break;
2648 case KEY_UP:
2649 nSysCode = VK_UP;
2650 nSysCode2 = (((ULONG)1) << 24);
2651 pReplace = "Up";
2652 break;
2653 case KEY_LEFT:
2654 nSysCode = VK_LEFT;
2655 nSysCode2 = (((ULONG)1) << 24);
2656 pReplace = "Left";
2657 break;
2658 case KEY_RIGHT:
2659 nSysCode = VK_RIGHT;
2660 nSysCode2 = (((ULONG)1) << 24);
2661 pReplace = "Right";
2662 break;
2663 case KEY_HOME:
2664 nSysCode = VK_HOME;
2665 nSysCode2 = (((ULONG)1) << 24);
2666 pReplace = "Home";
2667 break;
2668 case KEY_END:
2669 nSysCode = VK_END;
2670 nSysCode2 = (((ULONG)1) << 24);
2671 pReplace = "End";
2672 break;
2673 case KEY_PAGEUP:
2674 nSysCode = VK_PRIOR;
2675 nSysCode2 = (((ULONG)1) << 24);
2676 pReplace = "Page Up";
2677 break;
2678 case KEY_PAGEDOWN:
2679 nSysCode = VK_NEXT;
2680 nSysCode2 = (((ULONG)1) << 24);
2681 pReplace = "Page Down";
2682 break;
2683 case KEY_RETURN:
2684 nSysCode = VK_RETURN;
2685 pReplace = "Enter";
2686 break;
2687 case KEY_ESCAPE:
2688 nSysCode = VK_ESCAPE;
2689 pReplace = "Escape";
2690 break;
2691 case KEY_TAB:
2692 nSysCode = VK_TAB;
2693 pReplace = "Tab";
2694 break;
2695 case KEY_BACKSPACE:
2696 nSysCode = VK_BACK;
2697 pReplace = "Backspace";
2698 break;
2699 case KEY_SPACE:
2700 nSysCode = VK_SPACE;
2701 pReplace = "Space";
2702 break;
2703 case KEY_INSERT:
2704 nSysCode = VK_INSERT;
2705 nSysCode2 = (((ULONG)1) << 24);
2706 pReplace = "Insert";
2707 break;
2708 case KEY_DELETE:
2709 nSysCode = VK_DELETE;
2710 nSysCode2 = (((ULONG)1) << 24);
2711 pReplace = "Delete";
2712 break;
2714 case KEY_ADD:
2715 cSVCode = '+';
2716 break;
2717 case KEY_SUBTRACT:
2718 cSVCode = '-';
2719 break;
2720 case KEY_MULTIPLY:
2721 cSVCode = '*';
2722 break;
2723 case KEY_DIVIDE:
2724 cSVCode = '/';
2725 break;
2726 case KEY_POINT:
2727 cSVCode = '.';
2728 break;
2729 case KEY_COMMA:
2730 cSVCode = ',';
2731 break;
2732 case KEY_LESS:
2733 cSVCode = '<';
2734 break;
2735 case KEY_GREATER:
2736 cSVCode = '>';
2737 break;
2738 case KEY_EQUAL:
2739 cSVCode = '=';
2740 break;
2744 if ( nSysCode )
2746 nSysCode = MapVirtualKey( (UINT)nSysCode, 0 );
2747 if ( nSysCode )
2748 nSysCode = (nSysCode << 16) | nSysCode2;
2749 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, pReplace );
2751 else
2753 if ( cSVCode )
2755 if ( nKeyBufLen > 0 )
2756 aKeyBuf[ nKeyBufLen++ ] = '+';
2757 if( nKeyBufLen < nMaxKeyLen )
2758 aKeyBuf[ nKeyBufLen++ ] = cSVCode;
2762 if( !nKeyBufLen )
2763 return XubString();
2765 return XubString( aKeyBuf, sal::static_int_cast< USHORT >(nKeyBufLen) );
2768 // -----------------------------------------------------------------------
2770 XubString WinSalFrame::GetSymbolKeyName( const XubString&, USHORT nKeyCode )
2772 return GetKeyName( nKeyCode );
2775 // -----------------------------------------------------------------------
2777 inline Color ImplWinColorToSal( COLORREF nColor )
2779 return Color( GetRValue( nColor ), GetGValue( nColor ), GetBValue( nColor ) );
2782 // -----------------------------------------------------------------------
2784 static void ImplSalUpdateStyleFontA( HDC hDC, const LOGFONTA& rLogFont, Font& rFont )
2786 ImplSalLogFontToFontA( hDC, rLogFont, rFont );
2788 // On Windows 9x, Windows NT we get sometimes very small sizes
2789 // (for example for the small Caption height).
2790 // So if it is MS Sans Serif, a none scalable font we use
2791 // 8 Point as the minimum control height, in all other cases
2792 // 6 Point is the smallest one
2793 if ( rFont.GetHeight() < 8 )
2795 if ( rtl_str_compareIgnoreAsciiCase( rLogFont.lfFaceName, "MS Sans Serif" ) == 0 )
2796 rFont.SetHeight( 8 );
2797 else if ( rFont.GetHeight() < 6 )
2798 rFont.SetHeight( 6 );
2802 // -----------------------------------------------------------------------
2804 static void ImplSalUpdateStyleFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont )
2806 ImplSalLogFontToFontW( hDC, rLogFont, rFont );
2808 // On Windows 9x, Windows NT we get sometimes very small sizes
2809 // (for example for the small Caption height).
2810 // So if it is MS Sans Serif, a none scalable font we use
2811 // 8 Point as the minimum control height, in all other cases
2812 // 6 Point is the smallest one
2813 if ( rFont.GetHeight() < 8 )
2815 if ( rtl_ustr_compareIgnoreAsciiCase( reinterpret_cast<const sal_Unicode*>(rLogFont.lfFaceName), reinterpret_cast<const sal_Unicode*>(L"MS Sans Serif") ) == 0 )
2816 rFont.SetHeight( 8 );
2817 else if ( rFont.GetHeight() < 6 )
2818 rFont.SetHeight( 6 );
2822 // -----------------------------------------------------------------------
2824 static long ImplA2I( const BYTE* pStr )
2826 long n = 0;
2827 int nSign = 1;
2829 if ( *pStr == '-' )
2831 nSign = -1;
2832 pStr++;
2835 while( (*pStr >= 48) && (*pStr <= 57) )
2837 n *= 10;
2838 n += ((*pStr) - 48);
2839 pStr++;
2842 n *= nSign;
2844 return n;
2847 // -----------------------------------------------------------------------
2849 void WinSalFrame::UpdateSettings( AllSettings& rSettings )
2851 MouseSettings aMouseSettings = rSettings.GetMouseSettings();
2852 aMouseSettings.SetDoubleClickTime( GetDoubleClickTime() );
2853 aMouseSettings.SetDoubleClickWidth( GetSystemMetrics( SM_CXDOUBLECLK ) );
2854 aMouseSettings.SetDoubleClickHeight( GetSystemMetrics( SM_CYDOUBLECLK ) );
2855 long nDragWidth = GetSystemMetrics( SM_CXDRAG );
2856 long nDragHeight = GetSystemMetrics( SM_CYDRAG );
2857 if ( nDragWidth )
2858 aMouseSettings.SetStartDragWidth( nDragWidth );
2859 if ( nDragHeight )
2860 aMouseSettings.SetStartDragHeight( nDragHeight );
2861 HKEY hRegKey;
2862 if ( RegOpenKey( HKEY_CURRENT_USER,
2863 "Control Panel\\Desktop",
2864 &hRegKey ) == ERROR_SUCCESS )
2866 BYTE aValueBuf[10];
2867 DWORD nValueSize = sizeof( aValueBuf );
2868 DWORD nType;
2869 if ( RegQueryValueEx( hRegKey, "MenuShowDelay", 0,
2870 &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
2872 if ( nType == REG_SZ )
2873 aMouseSettings.SetMenuDelay( (ULONG)ImplA2I( aValueBuf ) );
2876 RegCloseKey( hRegKey );
2879 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
2880 BOOL bCompBorder = (aStyleSettings.GetOptions() & (STYLE_OPTION_MACSTYLE | STYLE_OPTION_UNIXSTYLE)) == 0;
2881 // TODO: once those options vanish: just set bCompBorder to TRUE
2882 // to have the system colors read
2883 aStyleSettings.SetScrollBarSize( Min( GetSystemMetrics( SM_CXVSCROLL ), 20 ) ); // #99956# do not allow huge scrollbars, most of the UI is not scaled anymore
2884 aStyleSettings.SetSpinSize( Min( GetSystemMetrics( SM_CXVSCROLL ), 20 ) );
2885 aStyleSettings.SetCursorBlinkTime( GetCaretBlinkTime() );
2886 if ( bCompBorder )
2888 aStyleSettings.SetFloatTitleHeight( GetSystemMetrics( SM_CYSMCAPTION ) );
2889 aStyleSettings.SetTitleHeight( GetSystemMetrics( SM_CYCAPTION ) );
2890 aStyleSettings.SetActiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVEBORDER ) ) );
2891 aStyleSettings.SetDeactiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVEBORDER ) ) );
2892 if ( aSalShlData.mnVersion >= 410 )
2894 aStyleSettings.SetActiveColor2( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTACTIVECAPTION ) ) );
2895 aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTINACTIVECAPTION ) ) );
2897 aStyleSettings.SetFaceColor( ImplWinColorToSal( GetSysColor( COLOR_3DFACE ) ) );
2898 aStyleSettings.SetInactiveTabColor( aStyleSettings.GetFaceColor() );
2899 aStyleSettings.SetLightColor( ImplWinColorToSal( GetSysColor( COLOR_3DHILIGHT ) ) );
2900 aStyleSettings.SetLightBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DLIGHT ) ) );
2901 aStyleSettings.SetShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
2902 aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DDKSHADOW ) ) );
2904 aStyleSettings.SetWorkspaceColor( ImplWinColorToSal( GetSysColor( COLOR_APPWORKSPACE ) ) );
2905 aStyleSettings.SetHelpColor( ImplWinColorToSal( GetSysColor( COLOR_INFOBK ) ) );
2906 aStyleSettings.SetHelpTextColor( ImplWinColorToSal( GetSysColor( COLOR_INFOTEXT ) ) );
2907 aStyleSettings.SetDialogColor( aStyleSettings.GetFaceColor() );
2908 aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() );
2909 aStyleSettings.SetButtonTextColor( ImplWinColorToSal( GetSysColor( COLOR_BTNTEXT ) ) );
2910 aStyleSettings.SetButtonRolloverTextColor( aStyleSettings.GetButtonTextColor() );
2911 aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
2912 aStyleSettings.SetGroupTextColor( aStyleSettings.GetRadioCheckTextColor() );
2913 aStyleSettings.SetLabelTextColor( aStyleSettings.GetRadioCheckTextColor() );
2914 aStyleSettings.SetInfoTextColor( aStyleSettings.GetRadioCheckTextColor() );
2915 aStyleSettings.SetWindowColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOW ) ) );
2916 aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() );
2917 aStyleSettings.SetWindowTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
2918 aStyleSettings.SetFieldColor( aStyleSettings.GetWindowColor() );
2919 aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() );
2920 aStyleSettings.SetFieldRolloverTextColor( aStyleSettings.GetFieldTextColor() );
2921 aStyleSettings.SetHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHT ) ) );
2922 aStyleSettings.SetHighlightTextColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHTTEXT ) ) );
2923 aStyleSettings.SetMenuHighlightColor( aStyleSettings.GetHighlightColor() );
2924 aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetHighlightTextColor() );
2925 if ( bCompBorder )
2927 aStyleSettings.SetMenuColor( ImplWinColorToSal( GetSysColor( COLOR_MENU ) ) );
2928 aStyleSettings.SetMenuBarColor( aStyleSettings.GetMenuColor() );
2929 aStyleSettings.SetMenuBorderColor( aStyleSettings.GetLightBorderColor() ); // overriden below for flat menus
2930 aStyleSettings.SetUseFlatBorders( FALSE );
2931 aStyleSettings.SetUseFlatMenues( FALSE );
2932 aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
2933 aStyleSettings.SetMenuBarTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
2934 aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) );
2935 aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) );
2936 aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) );
2937 aStyleSettings.SetDeactiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ) );
2938 if ( aSalShlData.mbWXP )
2940 // only xp supports a different menu bar color
2941 long bFlatMenues = 0;
2942 SystemParametersInfo( SPI_GETFLATMENU, 0, &bFlatMenues, 0);
2943 if( bFlatMenues )
2945 aStyleSettings.SetUseFlatMenues( TRUE );
2946 aStyleSettings.SetMenuBarColor( ImplWinColorToSal( GetSysColor( COLOR_MENUBAR ) ) );
2947 aStyleSettings.SetMenuHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_MENUHILIGHT ) ) );
2948 aStyleSettings.SetMenuBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
2950 // flat borders for our controls etc. as well in this mode (ie, no 3d borders)
2951 // this is not active in the classic style appearance
2952 aStyleSettings.SetUseFlatBorders( TRUE );
2956 // Bei hellgrau geben wir die Farbe vor, damit es besser aussieht
2957 if ( aStyleSettings.GetFaceColor() == COL_LIGHTGRAY )
2958 aStyleSettings.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
2959 else
2961 // Checked-Color berechnen
2962 Color aColor1 = aStyleSettings.GetFaceColor();
2963 Color aColor2 = aStyleSettings.GetLightColor();
2964 BYTE nRed = (BYTE)(((USHORT)aColor1.GetRed() + (USHORT)aColor2.GetRed())/2);
2965 BYTE nGreen = (BYTE)(((USHORT)aColor1.GetGreen() + (USHORT)aColor2.GetGreen())/2);
2966 BYTE nBlue = (BYTE)(((USHORT)aColor1.GetBlue() + (USHORT)aColor2.GetBlue())/2);
2967 aStyleSettings.SetCheckedColor( Color( nRed, nGreen, nBlue ) );
2970 // High contrast
2971 HIGHCONTRAST hc;
2972 hc.cbSize = sizeof( HIGHCONTRAST );
2973 if( SystemParametersInfo( SPI_GETHIGHCONTRAST, hc.cbSize, &hc, 0) && (hc.dwFlags & HCF_HIGHCONTRASTON) )
2974 aStyleSettings.SetHighContrastMode( 1 );
2975 else
2976 aStyleSettings.SetHighContrastMode( 0 );
2979 // Query Fonts
2980 Font aMenuFont = aStyleSettings.GetMenuFont();
2981 Font aTitleFont = aStyleSettings.GetTitleFont();
2982 Font aFloatTitleFont = aStyleSettings.GetFloatTitleFont();
2983 Font aHelpFont = aStyleSettings.GetHelpFont();
2984 Font aAppFont = aStyleSettings.GetAppFont();
2985 Font aIconFont = aStyleSettings.GetIconFont();
2986 HDC hDC = GetDC( 0 );
2987 if ( aSalShlData.mbWNT )
2989 NONCLIENTMETRICSW aNonClientMetrics;
2990 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
2991 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
2993 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMenuFont, aMenuFont );
2994 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont );
2995 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont );
2996 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfStatusFont, aHelpFont );
2997 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMessageFont, aAppFont );
2999 LOGFONTW aLogFont;
3000 if ( SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) )
3001 ImplSalUpdateStyleFontW( hDC, aLogFont, aIconFont );
3004 else
3006 NONCLIENTMETRICSA aNonClientMetrics;
3007 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
3008 if ( SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
3010 ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfMenuFont, aMenuFont );
3011 ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont );
3012 ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont );
3013 ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfStatusFont, aHelpFont );
3014 ImplSalUpdateStyleFontA( hDC, aNonClientMetrics.lfMessageFont, aAppFont );
3016 LOGFONTA aLogFont;
3017 if ( SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) )
3018 ImplSalUpdateStyleFontA( hDC, aLogFont, aIconFont );
3022 // get screen font resolution to calculate toolbox item size
3023 long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY );
3025 ReleaseDC( 0, hDC );
3027 long nHeightPx = aMenuFont.GetHeight() * nDPIY / 72;
3028 aStyleSettings.SetToolbarIconSize( (((nHeightPx-1)*2) >= 28) ? STYLE_TOOLBAR_ICONSIZE_LARGE : STYLE_TOOLBAR_ICONSIZE_SMALL );
3030 aStyleSettings.SetMenuFont( aMenuFont );
3031 aStyleSettings.SetTitleFont( aTitleFont );
3032 aStyleSettings.SetFloatTitleFont( aFloatTitleFont );
3033 aStyleSettings.SetHelpFont( aHelpFont );
3034 aStyleSettings.SetIconFont( aIconFont );
3035 // We prefer Arial in the russian version, because MS Sans Serif
3036 // is to wide for the dialogs
3037 if ( rSettings.GetLanguage() == LANGUAGE_RUSSIAN )
3039 XubString aFontName = aAppFont.GetName();
3040 XubString aFirstName = aFontName.GetToken( 0, ';' );
3041 if ( aFirstName.EqualsIgnoreCaseAscii( "MS Sans Serif" ) )
3043 aFontName.InsertAscii( "Arial;", 0 );
3044 aAppFont.SetName( aFontName );
3047 aStyleSettings.SetAppFont( aAppFont );
3048 aStyleSettings.SetGroupFont( aAppFont );
3049 aStyleSettings.SetLabelFont( aAppFont );
3050 aStyleSettings.SetRadioCheckFont( aAppFont );
3051 aStyleSettings.SetPushButtonFont( aAppFont );
3052 aStyleSettings.SetFieldFont( aAppFont );
3053 if ( aAppFont.GetWeight() > WEIGHT_NORMAL )
3054 aAppFont.SetWeight( WEIGHT_NORMAL );
3055 aStyleSettings.SetInfoFont( aAppFont );
3056 aStyleSettings.SetToolFont( aAppFont );
3058 WIN_BOOL bDragFull;
3059 if ( SystemParametersInfo( SPI_GETDRAGFULLWINDOWS, 0, &bDragFull, 0 ) )
3061 ULONG nDragFullOptions = aStyleSettings.GetDragFullOptions();
3062 if ( bDragFull )
3063 nDragFullOptions |= DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT;
3064 else
3065 nDragFullOptions &= ~(DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT);
3066 aStyleSettings.SetDragFullOptions( nDragFullOptions );
3069 aStyleSettings.SetIconHorzSpace( GetSystemMetrics( SM_CXICONSPACING ) );
3070 aStyleSettings.SetIconVertSpace( GetSystemMetrics( SM_CYICONSPACING ) );
3071 if ( RegOpenKey( HKEY_CURRENT_USER,
3072 "Control Panel\\International\\Calendars\\TwoDigitYearMax",
3073 &hRegKey ) == ERROR_SUCCESS )
3075 BYTE aValueBuf[10];
3076 DWORD nValue;
3077 DWORD nValueSize = sizeof( aValueBuf );
3078 DWORD nType;
3079 if ( RegQueryValueEx( hRegKey, "1", 0,
3080 &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
3082 if ( nType == REG_SZ )
3084 nValue = (ULONG)ImplA2I( aValueBuf );
3085 if ( (nValue > 1000) && (nValue < 10000) )
3087 MiscSettings aMiscSettings = rSettings.GetMiscSettings();
3088 aMiscSettings.SetTwoDigitYearStart( (USHORT)(nValue-99) );
3089 rSettings.SetMiscSettings( aMiscSettings );
3094 RegCloseKey( hRegKey );
3097 rSettings.SetMouseSettings( aMouseSettings );
3098 rSettings.SetStyleSettings( aStyleSettings );
3101 // -----------------------------------------------------------------------
3103 SalBitmap* WinSalFrame::SnapShot()
3105 WinSalBitmap* pSalBitmap = NULL;
3107 RECT aRect;
3108 GetWindowRect( mhWnd, &aRect );
3110 int nDX = aRect.right-aRect.left;
3111 int nDY = aRect.bottom-aRect.top;
3112 HDC hDC = GetWindowDC( mhWnd );
3113 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY );
3114 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap );
3115 BOOL bRet;
3117 bRet = BitBlt( hBmpDC, 0, 0, nDX, nDY, hDC, 0, 0, SRCCOPY ) ? TRUE : FALSE;
3118 ImplReleaseCachedDC( CACHED_HDC_1 );
3120 if ( bRet )
3122 pSalBitmap = new WinSalBitmap;
3124 if ( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) )
3126 delete pSalBitmap;
3127 pSalBitmap = NULL;
3131 return pSalBitmap;
3134 // -----------------------------------------------------------------------
3136 const SystemEnvData* WinSalFrame::GetSystemData() const
3138 return &maSysData;
3141 // -----------------------------------------------------------------------
3143 void WinSalFrame::Beep( SoundType eSoundType )
3145 static UINT aImplSoundTab[5] =
3147 0, // SOUND_DEFAULT
3148 MB_ICONASTERISK, // SOUND_INFO
3149 MB_ICONEXCLAMATION, // SOUND_WARNING
3150 MB_ICONHAND, // SOUND_ERROR
3151 MB_ICONQUESTION // SOUND_QUERY
3154 if( eSoundType != SOUND_DISABLE ) // don't beep on disable
3155 MessageBeep( aImplSoundTab[eSoundType] );
3158 // -----------------------------------------------------------------------
3160 SalFrame::SalPointerState WinSalFrame::GetPointerState()
3162 SalPointerState aState;
3163 aState.mnState = 0;
3165 if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
3166 aState.mnState |= MOUSE_LEFT;
3167 if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
3168 aState.mnState |= MOUSE_MIDDLE;
3169 if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
3170 aState.mnState |= MOUSE_RIGHT;
3171 if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3172 aState.mnState |= KEY_SHIFT;
3173 if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3174 aState.mnState |= KEY_MOD1;
3175 if ( GetKeyState( VK_MENU ) & 0x8000 )
3176 aState.mnState |= KEY_MOD2;
3178 POINT pt;
3179 GetCursorPos( &pt );
3181 aState.maPos = Point( pt.x - maGeometry.nX, pt.y - maGeometry.nY );
3182 return aState;
3185 // -----------------------------------------------------------------------
3187 SalFrame::SalIndicatorState WinSalFrame::GetIndicatorState()
3189 SalIndicatorState aState;
3190 aState.mnState = 0;
3191 if (::GetKeyState(VK_CAPITAL))
3192 aState.mnState |= INDICATOR_CAPSLOCK;
3194 if (::GetKeyState(VK_NUMLOCK))
3195 aState.mnState |= INDICATOR_NUMLOCK;
3197 if (::GetKeyState(VK_SCROLL))
3198 aState.mnState |= INDICATOR_SCROLLLOCK;
3200 return aState;
3203 void WinSalFrame::SimulateKeyPress( USHORT nKeyCode )
3205 BYTE nVKey = 0;
3206 switch (nKeyCode)
3208 case KEY_CAPSLOCK:
3209 nVKey = VK_CAPITAL;
3210 break;
3213 if (nVKey > 0 && nVKey < 255)
3215 ::keybd_event(nVKey, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
3216 ::keybd_event(nVKey, 0x45, KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP, 0);
3220 // -----------------------------------------------------------------------
3222 void WinSalFrame::SetBackgroundBitmap( SalBitmap* )
3226 // -----------------------------------------------------------------------
3228 void WinSalFrame::ResetClipRegion()
3230 SetWindowRgn( mhWnd, 0, TRUE );
3233 // -----------------------------------------------------------------------
3235 void WinSalFrame::BeginSetClipRegion( ULONG nRects )
3237 if( mpClipRgnData )
3238 delete [] (BYTE*)mpClipRgnData;
3239 ULONG nRectBufSize = sizeof(RECT)*nRects;
3240 mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize];
3241 mpClipRgnData->rdh.dwSize = sizeof( RGNDATAHEADER );
3242 mpClipRgnData->rdh.iType = RDH_RECTANGLES;
3243 mpClipRgnData->rdh.nCount = nRects;
3244 mpClipRgnData->rdh.nRgnSize = nRectBufSize;
3245 SetRectEmpty( &(mpClipRgnData->rdh.rcBound) );
3246 mpNextClipRect = (RECT*)(&(mpClipRgnData->Buffer));
3247 mbFirstClipRect = TRUE;
3250 // -----------------------------------------------------------------------
3252 void WinSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
3254 if( ! mpClipRgnData )
3255 return;
3257 RECT* pRect = mpNextClipRect;
3258 RECT* pBoundRect = &(mpClipRgnData->rdh.rcBound);
3259 long nRight = nX + nWidth;
3260 long nBottom = nY + nHeight;
3262 if ( mbFirstClipRect )
3264 pBoundRect->left = nX;
3265 pBoundRect->top = nY;
3266 pBoundRect->right = nRight;
3267 pBoundRect->bottom = nBottom;
3268 mbFirstClipRect = FALSE;
3270 else
3272 if ( nX < pBoundRect->left )
3273 pBoundRect->left = (int)nX;
3275 if ( nY < pBoundRect->top )
3276 pBoundRect->top = (int)nY;
3278 if ( nRight > pBoundRect->right )
3279 pBoundRect->right = (int)nRight;
3281 if ( nBottom > pBoundRect->bottom )
3282 pBoundRect->bottom = (int)nBottom;
3285 pRect->left = (int)nX;
3286 pRect->top = (int)nY;
3287 pRect->right = (int)nRight;
3288 pRect->bottom = (int)nBottom;
3289 if( (mpNextClipRect - (RECT*)(&mpClipRgnData->Buffer)) < (int)mpClipRgnData->rdh.nCount )
3290 mpNextClipRect++;
3293 // -----------------------------------------------------------------------
3295 void WinSalFrame::EndSetClipRegion()
3297 if( ! mpClipRgnData )
3298 return;
3300 HRGN hRegion;
3302 // create region from accumulated rectangles
3303 if ( mpClipRgnData->rdh.nCount == 1 )
3305 RECT* pRect = &(mpClipRgnData->rdh.rcBound);
3306 hRegion = CreateRectRgn( pRect->left, pRect->top,
3307 pRect->right, pRect->bottom );
3309 else
3311 ULONG nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER);
3312 hRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData );
3314 delete [] (BYTE*)mpClipRgnData;
3315 mpClipRgnData = NULL;
3317 DBG_ASSERT( hRegion, "WinSalFrame::EndSetClipRegion() - Can't create ClipRegion" );
3318 if( hRegion )
3320 RECT aWindowRect;
3321 GetWindowRect( mhWnd, &aWindowRect );
3322 POINT aPt;
3323 aPt.x=0;
3324 aPt.y=0;
3325 ClientToScreen( mhWnd, &aPt );
3326 OffsetRgn( hRegion, aPt.x - aWindowRect.left, aPt.y - aWindowRect.top );
3328 if( SetWindowRgn( mhWnd, hRegion, TRUE ) == 0 )
3329 DeleteObject( hRegion );
3333 // -----------------------------------------------------------------------
3335 static long ImplHandleMouseMsg( HWND hWnd, UINT nMsg,
3336 WPARAM wParam, LPARAM lParam )
3338 WinSalFrame* pFrame = GetWindowPtr( hWnd );
3339 if ( !pFrame )
3340 return 0;
3342 if( nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN || nMsg == WM_RBUTTONDOWN )
3344 // #103168# post again if async focus has not arrived yet
3345 // hopefully we will not receive the corresponding button up before this
3346 // button down arrives again
3347 Window *pWin = pFrame->GetWindow();
3348 if( pWin && pWin->ImplGetWindowImpl()->mpFrameData->mnFocusId )
3350 ImplPostMessage( hWnd, nMsg, wParam, lParam );
3351 return 1;
3354 SalMouseEvent aMouseEvt;
3355 long nRet;
3356 USHORT nEvent = 0;
3357 BOOL bCall = TRUE;
3359 aMouseEvt.mnX = (short)LOWORD( lParam );
3360 aMouseEvt.mnY = (short)HIWORD( lParam );
3361 aMouseEvt.mnCode = 0;
3362 aMouseEvt.mnTime = GetMessageTime();
3364 // Wegen (Logitech-)MouseTreiber ueber GetKeyState() gehen, die auf
3365 // mittlerer Maustaste Doppelklick simulieren und den KeyStatus nicht
3366 // beruecksichtigen
3368 if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
3369 aMouseEvt.mnCode |= MOUSE_LEFT;
3370 if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
3371 aMouseEvt.mnCode |= MOUSE_MIDDLE;
3372 if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
3373 aMouseEvt.mnCode |= MOUSE_RIGHT;
3374 if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3375 aMouseEvt.mnCode |= KEY_SHIFT;
3376 if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3377 aMouseEvt.mnCode |= KEY_MOD1;
3378 if ( GetKeyState( VK_MENU ) & 0x8000 )
3379 aMouseEvt.mnCode |= KEY_MOD2;
3381 switch ( nMsg )
3383 case WM_MOUSEMOVE:
3385 // Da bei Druecken von Modifier-Tasten die MouseEvents
3386 // nicht zusammengefast werden (da diese durch KeyEvents
3387 // unterbrochen werden), machen wir dieses hier selber
3388 if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) )
3390 MSG aTempMsg;
3391 if ( ImplPeekMessage( &aTempMsg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE | PM_NOYIELD ) )
3393 if ( (aTempMsg.message == WM_MOUSEMOVE) &&
3394 (aTempMsg.wParam == wParam) )
3395 return 1;
3399 SalData* pSalData = GetSalData();
3400 // Test for MouseLeave
3401 if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) )
3402 ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() );
3404 pSalData->mhWantLeaveMsg = hWnd;
3405 // Start MouseLeave-Timer
3406 if ( !pSalData->mpMouseLeaveTimer )
3408 pSalData->mpMouseLeaveTimer = new AutoTimer;
3409 pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT );
3410 pSalData->mpMouseLeaveTimer->Start();
3411 // We dont need to set a timeout handler, because we test
3412 // for mouseleave in the timeout callback
3414 aMouseEvt.mnButton = 0;
3415 nEvent = SALEVENT_MOUSEMOVE;
3417 break;
3419 case WM_NCMOUSEMOVE:
3420 case SAL_MSG_MOUSELEAVE:
3422 SalData* pSalData = GetSalData();
3423 if ( pSalData->mhWantLeaveMsg == hWnd )
3425 pSalData->mhWantLeaveMsg = 0;
3426 if ( pSalData->mpMouseLeaveTimer )
3428 delete pSalData->mpMouseLeaveTimer;
3429 pSalData->mpMouseLeaveTimer = NULL;
3431 // Mouse-Coordinaates are relativ to the screen
3432 POINT aPt;
3433 aPt.x = (short)LOWORD( lParam );
3434 aPt.y = (short)HIWORD( lParam );
3435 ScreenToClient( hWnd, &aPt );
3436 aMouseEvt.mnX = aPt.x;
3437 aMouseEvt.mnY = aPt.y;
3438 aMouseEvt.mnButton = 0;
3439 nEvent = SALEVENT_MOUSELEAVE;
3441 else
3442 bCall = FALSE;
3444 break;
3446 case WM_LBUTTONDOWN:
3447 aMouseEvt.mnButton = MOUSE_LEFT;
3448 nEvent = SALEVENT_MOUSEBUTTONDOWN;
3449 break;
3451 case WM_MBUTTONDOWN:
3452 aMouseEvt.mnButton = MOUSE_MIDDLE;
3453 nEvent = SALEVENT_MOUSEBUTTONDOWN;
3454 break;
3456 case WM_RBUTTONDOWN:
3457 aMouseEvt.mnButton = MOUSE_RIGHT;
3458 nEvent = SALEVENT_MOUSEBUTTONDOWN;
3459 break;
3461 case WM_LBUTTONUP:
3462 aMouseEvt.mnButton = MOUSE_LEFT;
3463 nEvent = SALEVENT_MOUSEBUTTONUP;
3464 break;
3466 case WM_MBUTTONUP:
3467 aMouseEvt.mnButton = MOUSE_MIDDLE;
3468 nEvent = SALEVENT_MOUSEBUTTONUP;
3469 break;
3471 case WM_RBUTTONUP:
3472 aMouseEvt.mnButton = MOUSE_RIGHT;
3473 nEvent = SALEVENT_MOUSEBUTTONUP;
3474 break;
3477 // check if this window was destroyed - this might happen if we are the help window
3478 // and sent a mouse leave message to the application which killed the help window, ie ourself
3479 if( !IsWindow( hWnd ) )
3480 return 0;
3482 if ( bCall )
3484 if ( nEvent == SALEVENT_MOUSEBUTTONDOWN )
3485 UpdateWindow( hWnd );
3487 // --- RTL --- (mirror mouse pos)
3488 if( Application::GetSettings().GetLayoutRTL() )
3489 aMouseEvt.mnX = pFrame->maGeometry.nWidth-1-aMouseEvt.mnX;
3491 nRet = pFrame->CallCallback( nEvent, &aMouseEvt );
3492 if ( nMsg == WM_MOUSEMOVE )
3493 SetCursor( pFrame->mhCursor );
3495 else
3496 nRet = 0;
3498 return nRet;
3501 // -----------------------------------------------------------------------
3503 static long ImplHandleMouseActivateMsg( HWND hWnd )
3505 WinSalFrame* pFrame = GetWindowPtr( hWnd );
3506 if ( !pFrame )
3507 return 0;
3509 if ( pFrame->mbFloatWin )
3510 return TRUE;
3512 SalMouseActivateEvent aMouseActivateEvt;
3513 POINT aPt;
3514 GetCursorPos( &aPt );
3515 ScreenToClient( hWnd, &aPt );
3516 aMouseActivateEvt.mnX = aPt.x;
3517 aMouseActivateEvt.mnY = aPt.y;
3518 return pFrame->CallCallback( SALEVENT_MOUSEACTIVATE, &aMouseActivateEvt );
3521 // -----------------------------------------------------------------------
3523 static long ImplHandleWheelMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
3525 DBG_ASSERT( nMsg == WM_MOUSEWHEEL ||
3526 nMsg == WM_MOUSEHWHEEL,
3527 "ImplHandleWheelMsg() called with no wheel mouse event" );
3529 ImplSalYieldMutexAcquireWithWait();
3531 long nRet = 0;
3532 WinSalFrame* pFrame = GetWindowPtr( hWnd );
3533 if ( pFrame )
3535 WORD nWinModCode = LOWORD( wParam );
3536 POINT aWinPt;
3537 aWinPt.x = (short)LOWORD( lParam );
3538 aWinPt.y = (short)HIWORD( lParam );
3539 ScreenToClient( hWnd, &aWinPt );
3541 SalWheelMouseEvent aWheelEvt;
3542 aWheelEvt.mnTime = GetMessageTime();
3543 aWheelEvt.mnX = aWinPt.x;
3544 aWheelEvt.mnY = aWinPt.y;
3545 aWheelEvt.mnCode = 0;
3546 aWheelEvt.mnDelta = (short)HIWORD( wParam );
3547 aWheelEvt.mnNotchDelta = aWheelEvt.mnDelta/WHEEL_DELTA;
3548 if( aWheelEvt.mnNotchDelta == 0 )
3550 if( aWheelEvt.mnDelta > 0 )
3551 aWheelEvt.mnNotchDelta = 1;
3552 else if( aWheelEvt.mnDelta < 0 )
3553 aWheelEvt.mnNotchDelta = -1;
3556 if( nMsg == WM_MOUSEWHEEL )
3558 if ( aSalShlData.mnWheelScrollLines == WHEEL_PAGESCROLL )
3559 aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
3560 else
3561 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollLines;
3562 aWheelEvt.mbHorz = FALSE;
3564 else
3566 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollChars;
3567 aWheelEvt.mbHorz = TRUE;
3570 if ( nWinModCode & MK_SHIFT )
3571 aWheelEvt.mnCode |= KEY_SHIFT;
3572 if ( nWinModCode & MK_CONTROL )
3573 aWheelEvt.mnCode |= KEY_MOD1;
3574 if ( GetKeyState( VK_MENU ) & 0x8000 )
3575 aWheelEvt.mnCode |= KEY_MOD2;
3577 // --- RTL --- (mirror mouse pos)
3578 if( Application::GetSettings().GetLayoutRTL() )
3579 aWheelEvt.mnX = pFrame->maGeometry.nWidth-1-aWheelEvt.mnX;
3581 nRet = pFrame->CallCallback( SALEVENT_WHEELMOUSE, &aWheelEvt );
3584 ImplSalYieldMutexRelease();
3586 return nRet;
3589 // -----------------------------------------------------------------------
3591 static USHORT ImplSalGetKeyCode( WPARAM wParam )
3593 USHORT nKeyCode;
3595 // convert KeyCode
3596 if ( wParam < KEY_TAB_SIZE )
3597 nKeyCode = aImplTranslateKeyTab[wParam];
3598 else
3600 SalData* pSalData = GetSalData();
3601 std::map< UINT, USHORT >::const_iterator it = pSalData->maVKMap.find( (UINT)wParam );
3602 if( it != pSalData->maVKMap.end() )
3603 nKeyCode = it->second;
3604 else
3605 nKeyCode = 0;
3608 return nKeyCode;
3611 // -----------------------------------------------------------------------
3613 static UINT ImplStrToNum( const sal_Char* pStr )
3615 USHORT n = 0;
3617 // Solange es sich um eine Ziffer handelt, String umwandeln
3618 while( (*pStr >= 48) && (*pStr <= 57) )
3620 n *= 10;
3621 n += ((*pStr) - 48);
3622 pStr++;
3625 return n;
3628 // -----------------------------------------------------------------------
3630 static void ImplUpdateInputLang( WinSalFrame* pFrame )
3632 BOOL bLanguageChange = FALSE;
3633 UINT nLang = LOWORD( GetKeyboardLayout( 0 ) );
3634 if ( nLang && nLang != pFrame->mnInputLang )
3636 // keep input lang up-to-date
3637 pFrame->mnInputLang = nLang;
3638 bLanguageChange = TRUE;
3641 // If we are on Windows NT we use Unicode FrameProcs and so we
3642 // get Unicode charcodes directly from Windows
3643 // no need to set up a code page
3644 if ( aSalShlData.mbWNT )
3645 return;
3647 if ( !nLang )
3649 pFrame->mnInputLang = 0;
3650 pFrame->mnInputCodePage = GetACP();
3652 else if ( bLanguageChange )
3654 sal_Char aBuf[10];
3655 if ( GetLocaleInfoA( MAKELCID( nLang, SORT_DEFAULT ), LOCALE_IDEFAULTANSICODEPAGE,
3656 aBuf, sizeof(aBuf) ) > 0 )
3658 pFrame->mnInputCodePage = ImplStrToNum( aBuf );
3659 if ( !pFrame->mnInputCodePage )
3660 pFrame->mnInputCodePage = GetACP();
3662 else
3663 pFrame->mnInputCodePage = GetACP();
3668 static sal_Unicode ImplGetCharCode( WinSalFrame* pFrame, WPARAM nCharCode )
3670 ImplUpdateInputLang( pFrame );
3672 // If we are on Windows NT we use Unicode FrameProcs and so we
3673 // get Unicode charcodes directly from Windows
3674 if ( aSalShlData.mbWNT )
3675 return (sal_Unicode)nCharCode;
3677 sal_Char aCharBuf[2];
3678 int nCharLen;
3679 WCHAR c;
3680 if ( nCharCode > 0xFF )
3682 aCharBuf[0] = (sal_Char)(nCharCode>>8);
3683 aCharBuf[1] = (sal_Char)nCharCode;
3684 nCharLen = 2;
3686 else
3688 aCharBuf[0] = (sal_Char)nCharCode;
3689 nCharLen = 1;
3691 if ( ::MultiByteToWideChar( pFrame->mnInputCodePage,
3692 MB_PRECOMPOSED,
3693 aCharBuf, nCharLen, &c, 1 ) )
3694 return (sal_Unicode)c;
3695 else
3696 return (sal_Unicode)nCharCode;
3699 // -----------------------------------------------------------------------
3701 LanguageType WinSalFrame::GetInputLanguage()
3703 if( !mnInputLang )
3704 ImplUpdateInputLang( this );
3706 if( !mnInputLang )
3707 return LANGUAGE_DONTKNOW;
3708 else
3709 return (LanguageType) mnInputLang;
3712 // -----------------------------------------------------------------------
3714 BOOL WinSalFrame::MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode )
3716 BOOL bRet = FALSE;
3717 HKL hkl = 0;
3719 // just use the passed language identifier, do not try to load additional keyboard support
3720 hkl = (HKL) aLangType;
3722 if( hkl )
3724 SHORT scan = VkKeyScanExW( aUnicode, hkl );
3725 if( LOWORD(scan) == 0xFFFF )
3726 // keyboard not loaded or key cannot be mapped
3727 bRet = FALSE;
3728 else
3730 BYTE vkeycode = LOBYTE(scan);
3731 BYTE shiftstate = HIBYTE(scan);
3733 // Last argument is set to FALSE, because there's no decission made
3734 // yet which key should be assigned to MOD3 modifier on Windows.
3735 // Windows key - user's can be confused, because it should display
3736 // Windows menu (applies to both left/right key)
3737 // Menu key - this key is used to display context menu
3738 // AltGr key - probably it has no sense
3739 rKeyCode = KeyCode( ImplSalGetKeyCode( vkeycode ),
3740 (shiftstate & 0x01) ? TRUE : FALSE, // shift
3741 (shiftstate & 0x02) ? TRUE : FALSE, // ctrl
3742 (shiftstate & 0x04) ? TRUE : FALSE, // alt
3743 FALSE );
3744 bRet = TRUE;
3748 return bRet;
3751 // -----------------------------------------------------------------------
3753 static long ImplHandleKeyMsg( HWND hWnd, UINT nMsg,
3754 WPARAM wParam, LPARAM lParam, LRESULT& rResult )
3756 static BOOL bIgnoreCharMsg = FALSE;
3757 static WPARAM nDeadChar = 0;
3758 static WPARAM nLastVKChar = 0;
3759 static USHORT nLastChar = 0;
3760 static USHORT nLastModKeyCode = 0;
3761 static bool bWaitForModKeyRelease = false;
3762 USHORT nRepeat = LOWORD( lParam )-1;
3763 USHORT nModCode = 0;
3765 // Key wurde evtl. durch SysChild an uns weitergeleitet und
3766 // darf somit dann nicht doppelt verarbeitet werden
3767 GetSalData()->mnSalObjWantKeyEvt = 0;
3769 if ( nMsg == WM_DEADCHAR )
3771 nDeadChar = wParam;
3772 return 0;
3775 WinSalFrame* pFrame = GetWindowPtr( hWnd );
3776 if ( !pFrame )
3777 return 0;
3779 // Wir restaurieren den Background-Modus bei jeder Texteingabe,
3780 // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
3781 if ( pFrame->mpGraphics &&
3782 pFrame->mpGraphics->mhDC )
3783 SetBkMode( pFrame->mpGraphics->mhDC, TRANSPARENT );
3785 // determine modifiers
3786 if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3787 nModCode |= KEY_SHIFT;
3788 if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3789 nModCode |= KEY_MOD1;
3790 if ( GetKeyState( VK_MENU ) & 0x8000 )
3791 nModCode |= KEY_MOD2;
3793 if ( (nMsg == WM_CHAR) || (nMsg == WM_SYSCHAR) )
3795 nDeadChar = 0;
3797 if ( bIgnoreCharMsg )
3799 bIgnoreCharMsg = FALSE;
3800 // #101635# if zero is returned here for WM_SYSCHAR (ALT+<key>) Windows will beep
3801 // becaus this 'hotkey' was not processed -> better return 1
3802 // except for Alt-SPACE which should always open the sysmenu (#104616#)
3804 // also return zero if a system menubar is available that might process this hotkey
3805 // this also applies to the OLE inplace embedding where we are a child window
3806 if( (GetWindowStyle( hWnd ) & WS_CHILD) || GetMenu( hWnd ) || (wParam == 0x20) )
3807 return 0;
3808 else
3809 return 1;
3812 // Backspace ignorieren wir als eigenstaendige Taste,
3813 // damit wir keine Probleme in Kombination mit einem
3814 // DeadKey bekommen
3815 if ( wParam == 0x08 ) // BACKSPACE
3816 return 0;
3818 // Hier kommen nur "freifliegende" WM_CHAR Message an, die durch
3819 // eintippen einer ALT-NUMPAD Kombination erzeugt wurden
3820 SalKeyEvent aKeyEvt;
3822 if ( (wParam >= '0') && (wParam <= '9') )
3823 aKeyEvt.mnCode = sal::static_int_cast<USHORT>(KEYGROUP_NUM + wParam - '0');
3824 else if ( (wParam >= 'A') && (wParam <= 'Z') )
3825 aKeyEvt.mnCode = sal::static_int_cast<USHORT>(KEYGROUP_ALPHA + wParam - 'A');
3826 else if ( (wParam >= 'a') && (wParam <= 'z') )
3827 aKeyEvt.mnCode = sal::static_int_cast<USHORT>(KEYGROUP_ALPHA + wParam - 'a');
3828 else if ( wParam == 0x0D ) // RETURN
3829 aKeyEvt.mnCode = KEY_RETURN;
3830 else if ( wParam == 0x1B ) // ESCAPE
3831 aKeyEvt.mnCode = KEY_ESCAPE;
3832 else if ( wParam == 0x09 ) // TAB
3833 aKeyEvt.mnCode = KEY_TAB;
3834 else if ( wParam == 0x20 ) // SPACE
3835 aKeyEvt.mnCode = KEY_SPACE;
3836 else
3837 aKeyEvt.mnCode = 0;
3839 aKeyEvt.mnTime = GetMessageTime();
3840 aKeyEvt.mnCode |= nModCode;
3841 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, wParam );
3842 aKeyEvt.mnRepeat = nRepeat;
3843 nLastChar = 0;
3844 nLastVKChar = 0;
3845 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3846 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3847 return nRet;
3849 // #i11583#, MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition begins
3850 else if( nMsg == WM_UNICHAR )
3852 // If Windows is asking if we accept WM_UNICHAR, return TRUE
3853 if(wParam == UNICODE_NOCHAR)
3855 rResult = TRUE; // ssa: this will actually return TRUE to windows
3856 return 1; // ...but this will only avoid calling the defwindowproc
3859 SalKeyEvent aKeyEvt;
3860 aKeyEvt.mnCode = nModCode; // Or should it be 0? - as this is always a character returned
3861 aKeyEvt.mnTime = GetMessageTime();
3862 aKeyEvt.mnRepeat = 0;
3864 if( wParam >= Uni_SupplementaryPlanesStart )
3866 // character is supplementary char in UTF-32 format - must be converted to UTF-16 supplementary pair
3867 // sal_Unicode ch = (sal_Unicode) Uni_UTF32ToSurrogate1(wParam);
3868 nLastChar = 0;
3869 nLastVKChar = 0;
3870 pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3871 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3872 wParam = (sal_Unicode) Uni_UTF32ToSurrogate2( wParam );
3875 aKeyEvt.mnCharCode = (sal_Unicode) wParam;
3877 nLastChar = 0;
3878 nLastVKChar = 0;
3879 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3880 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3882 return nRet;
3884 // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition ends
3885 else
3887 // Bei Shift, Control und Menu schicken wir einen KeyModChange-Event
3888 if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) )
3890 SalKeyModEvent aModEvt;
3891 aModEvt.mnTime = GetMessageTime();
3892 aModEvt.mnCode = nModCode;
3893 aModEvt.mnModKeyCode = 0; // no command events will be sent if this member is 0
3895 USHORT tmpCode = 0;
3896 if( GetKeyState( VK_LSHIFT ) & 0x8000 )
3897 tmpCode |= MODKEY_LSHIFT;
3898 if( GetKeyState( VK_RSHIFT ) & 0x8000 )
3899 tmpCode |= MODKEY_RSHIFT;
3900 if( GetKeyState( VK_LCONTROL ) & 0x8000 )
3901 tmpCode |= MODKEY_LMOD1;
3902 if( GetKeyState( VK_RCONTROL ) & 0x8000 )
3903 tmpCode |= MODKEY_RMOD1;
3904 if( GetKeyState( VK_LMENU ) & 0x8000 )
3905 tmpCode |= MODKEY_LMOD2;
3906 if( GetKeyState( VK_RMENU ) & 0x8000 )
3907 tmpCode |= MODKEY_RMOD2;
3909 if( tmpCode < nLastModKeyCode )
3911 aModEvt.mnModKeyCode = nLastModKeyCode;
3912 nLastModKeyCode = 0;
3913 bWaitForModKeyRelease = true;
3915 else
3917 if( !bWaitForModKeyRelease )
3918 nLastModKeyCode = tmpCode;
3921 if( !tmpCode )
3922 bWaitForModKeyRelease = false;
3924 return pFrame->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
3926 else
3928 SalKeyEvent aKeyEvt;
3929 USHORT nEvent;
3930 MSG aCharMsg;
3931 WIN_BOOL bCharPeek = FALSE;
3932 UINT nCharMsg = WM_CHAR;
3933 BOOL bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
3935 nLastModKeyCode = 0; // make sure no modkey messages are sent if they belong to a hotkey (see above)
3936 aKeyEvt.mnCharCode = 0;
3937 aKeyEvt.mnCode = 0;
3939 aKeyEvt.mnCode = ImplSalGetKeyCode( wParam );
3940 if ( !bKeyUp )
3942 // check for charcode
3943 // Mit Hilfe von PeekMessage holen wir uns jetzt die
3944 // zugehoerige WM_CHAR Message, wenn vorhanden.
3945 // Diese WM_CHAR Message steht immer am Anfang der
3946 // Messagequeue. Ausserdem ist sichergestellt, dass immer
3947 // nur eine WM_CHAR Message in der Queue steht.
3948 bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
3949 WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD );
3950 if ( bCharPeek && (nDeadChar == aCharMsg.wParam) )
3952 bCharPeek = FALSE;
3953 nDeadChar = 0;
3955 if ( wParam == VK_BACK )
3957 ImplPeekMessage( &aCharMsg, hWnd,
3958 nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
3959 return 0;
3962 else
3964 if ( !bCharPeek )
3966 bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
3967 WM_SYSCHAR, WM_SYSCHAR, PM_NOREMOVE | PM_NOYIELD );
3968 nCharMsg = WM_SYSCHAR;
3971 if ( bCharPeek )
3972 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, aCharMsg.wParam );
3973 else
3974 aKeyEvt.mnCharCode = 0;
3976 nLastChar = aKeyEvt.mnCharCode;
3977 nLastVKChar = wParam;
3979 else
3981 if ( wParam == nLastVKChar )
3983 aKeyEvt.mnCharCode = nLastChar;
3984 nLastChar = 0;
3985 nLastVKChar = 0;
3989 if ( aKeyEvt.mnCode || aKeyEvt.mnCharCode )
3991 if ( bKeyUp )
3992 nEvent = SALEVENT_KEYUP;
3993 else
3994 nEvent = SALEVENT_KEYINPUT;
3996 aKeyEvt.mnTime = GetMessageTime();
3997 aKeyEvt.mnCode |= nModCode;
3998 aKeyEvt.mnRepeat = nRepeat;
4000 if( (nModCode & (KEY_MOD1|KEY_MOD2)) == (KEY_MOD1|KEY_MOD2) &&
4001 aKeyEvt.mnCharCode )
4003 // this is actually AltGr and should not be handled as Alt
4004 aKeyEvt.mnCode &= ~(KEY_MOD1|KEY_MOD2);
4007 bIgnoreCharMsg = bCharPeek ? TRUE : FALSE;
4008 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt );
4009 // independent part only reacts on keyup but Windows does not send
4010 // keyup for VK_HANJA
4011 if( aKeyEvt.mnCode == KEY_HANGUL_HANJA )
4012 nRet = pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
4014 bIgnoreCharMsg = FALSE;
4016 // char-message, than remove or ignore
4017 if ( bCharPeek )
4019 nDeadChar = 0;
4020 if ( nRet )
4022 ImplPeekMessage( &aCharMsg, hWnd,
4023 nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
4025 else
4026 bIgnoreCharMsg = TRUE;
4029 return nRet;
4031 else
4032 return 0;
4037 // -----------------------------------------------------------------------
4039 long ImplHandleSalObjKeyMsg( HWND hWnd, UINT nMsg,
4040 WPARAM wParam, LPARAM lParam )
4042 if ( (nMsg == WM_KEYDOWN) || (nMsg == WM_KEYUP) )
4044 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4045 if ( !pFrame )
4046 return 0;
4048 USHORT nRepeat = LOWORD( lParam )-1;
4049 USHORT nModCode = 0;
4051 // determine modifiers
4052 if ( GetKeyState( VK_SHIFT ) & 0x8000 )
4053 nModCode |= KEY_SHIFT;
4054 if ( GetKeyState( VK_CONTROL ) & 0x8000 )
4055 nModCode |= KEY_MOD1;
4056 if ( GetKeyState( VK_MENU ) & 0x8000 )
4057 nModCode |= KEY_MOD2;
4059 if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) && (wParam != VK_MENU) )
4061 SalKeyEvent aKeyEvt;
4062 USHORT nEvent;
4063 BOOL bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
4065 // convert KeyCode
4066 aKeyEvt.mnCode = ImplSalGetKeyCode( wParam );
4067 aKeyEvt.mnCharCode = 0;
4069 if ( aKeyEvt.mnCode )
4071 if ( bKeyUp )
4072 nEvent = SALEVENT_KEYUP;
4073 else
4074 nEvent = SALEVENT_KEYINPUT;
4076 aKeyEvt.mnTime = GetMessageTime();
4077 aKeyEvt.mnCode |= nModCode;
4078 aKeyEvt.mnRepeat = nRepeat;
4079 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt );
4080 return nRet;
4082 else
4083 return 0;
4087 return 0;
4090 // -----------------------------------------------------------------------
4092 long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
4094 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4095 if ( !pFrame )
4096 return 0;
4098 USHORT nRepeat = LOWORD( lParam )-1;
4099 USHORT nModCode = 0;
4100 USHORT cKeyCode = (USHORT)wParam;
4102 // determine modifiers
4103 if ( GetKeyState( VK_SHIFT ) & 0x8000 )
4104 nModCode |= KEY_SHIFT;
4105 if ( GetKeyState( VK_CONTROL ) & 0x8000 )
4106 nModCode |= KEY_MOD1;
4107 nModCode |= KEY_MOD2;
4109 // KeyEvent zusammenbauen
4110 SalKeyEvent aKeyEvt;
4111 aKeyEvt.mnTime = GetMessageTime();
4112 if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
4113 aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
4114 else if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
4115 aKeyEvt.mnCode = KEY_A+(cKeyCode-65);
4116 else if ( (cKeyCode >= 97) && (cKeyCode <= 122) )
4117 aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
4118 else
4119 aKeyEvt.mnCode = 0;
4120 aKeyEvt.mnCode |= nModCode;
4121 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, cKeyCode );
4122 aKeyEvt.mnRepeat = nRepeat;
4123 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
4124 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
4125 return nRet;
4128 // -----------------------------------------------------------------------
4130 static bool ImplHandlePaintMsg( HWND hWnd )
4132 BOOL bMutex = FALSE;
4133 if ( ImplSalYieldMutexTryToAcquire() )
4134 bMutex = TRUE;
4136 // if we don't get the mutex, we can also change the clip region,
4137 // because other threads doesn't use the mutex from the main
4138 // thread --> see GetGraphics()
4140 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4141 if ( pFrame )
4143 // Clip-Region muss zurueckgesetzt werden, da wir sonst kein
4144 // ordentliches Bounding-Rectangle bekommen
4145 if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4146 SelectClipRgn( pFrame->mpGraphics->mhDC, 0 );
4148 // Laut Window-Doku soll man erst abfragen, ob ueberhaupt eine
4149 // Paint-Region anliegt
4150 if ( GetUpdateRect( hWnd, NULL, FALSE ) )
4152 // Call BeginPaint/EndPaint to query the rect and send
4153 // this Notofication to rect
4154 RECT aUpdateRect;
4155 PAINTSTRUCT aPs;
4156 BeginPaint( hWnd, &aPs );
4157 CopyRect( &aUpdateRect, &aPs.rcPaint );
4159 // Paint
4160 // ClipRegion wieder herstellen
4161 if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4163 SelectClipRgn( pFrame->mpGraphics->mhDC,
4164 pFrame->mpGraphics->mhRegion );
4167 if ( bMutex )
4169 SalPaintEvent aPEvt( aUpdateRect.left, aUpdateRect.top, aUpdateRect.right-aUpdateRect.left, aUpdateRect.bottom-aUpdateRect.top, pFrame->mbPresentation );
4170 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
4172 else
4174 RECT* pRect = new RECT;
4175 CopyRect( pRect, &aUpdateRect );
4176 ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
4178 EndPaint( hWnd, &aPs );
4180 else
4182 // ClipRegion wieder herstellen
4183 if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4185 SelectClipRgn( pFrame->mpGraphics->mhDC,
4186 pFrame->mpGraphics->mhRegion );
4191 if ( bMutex )
4192 ImplSalYieldMutexRelease();
4194 return bMutex ? true : false;
4197 // -----------------------------------------------------------------------
4199 static void ImplHandlePaintMsg2( HWND hWnd, RECT* pRect )
4201 // Paint
4202 if ( ImplSalYieldMutexTryToAcquire() )
4204 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4205 if ( pFrame )
4207 SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
4208 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
4210 ImplSalYieldMutexRelease();
4211 delete pRect;
4213 else
4214 ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
4217 // -----------------------------------------------------------------------
4219 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame )
4221 // calculate and set frame geometry of a maximized window - useful if the window is still hidden
4223 // dualmonitor support:
4224 // Get screensize of the monitor whith the mouse pointer
4226 POINT pt;
4227 GetCursorPos( &pt );
4228 RECT aRectMouse;
4229 aRectMouse.left = pt.x;
4230 aRectMouse.top = pt.y;
4231 aRectMouse.right = pt.x+2;
4232 aRectMouse.bottom = pt.y+2;
4234 RECT aRect;
4235 ImplSalGetWorkArea( hWnd, &aRect, &aRectMouse );
4237 // a maximized window has no other borders than the caption
4238 pFrame->maGeometry.nLeftDecoration = pFrame->maGeometry.nRightDecoration = pFrame->maGeometry.nBottomDecoration = 0;
4239 pFrame->maGeometry.nTopDecoration = pFrame->mbCaption ? GetSystemMetrics( SM_CYCAPTION ) : 0;
4241 aRect.top += pFrame->maGeometry.nTopDecoration;
4242 pFrame->maGeometry.nX = aRect.left;
4243 pFrame->maGeometry.nY = aRect.top;
4244 pFrame->maGeometry.nWidth = aRect.right - aRect.left;
4245 pFrame->maGeometry.nHeight = aRect.bottom - aRect.top;
4248 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame )
4250 if( !pFrame )
4251 return;
4253 RECT aRect;
4254 GetWindowRect( hWnd, &aRect );
4255 memset(&pFrame->maGeometry, 0, sizeof(SalFrameGeometry) );
4257 if ( IsIconic( hWnd ) )
4258 return;
4260 POINT aPt;
4261 aPt.x=0;
4262 aPt.y=0;
4263 ClientToScreen(hWnd, &aPt);
4264 int cx = aPt.x - aRect.left;
4265 pFrame->maGeometry.nTopDecoration = aPt.y - aRect.top;
4267 pFrame->maGeometry.nLeftDecoration = cx;
4268 pFrame->maGeometry.nRightDecoration = cx;
4270 pFrame->maGeometry.nX = aPt.x;
4271 pFrame->maGeometry.nY = aPt.y;
4273 RECT aInnerRect;
4274 GetClientRect( hWnd, &aInnerRect );
4275 if( aInnerRect.right )
4277 // improve right decoration
4278 aPt.x=aInnerRect.right;
4279 aPt.y=aInnerRect.top;
4280 ClientToScreen(hWnd, &aPt);
4281 pFrame->maGeometry.nRightDecoration = aRect.right - aPt.x;
4283 if( aInnerRect.bottom ) // may be zero if window was not shown yet
4284 pFrame->maGeometry.nBottomDecoration += aRect.bottom - aPt.y - aInnerRect.bottom;
4285 else
4286 // bottom border is typically the same as left/right
4287 pFrame->maGeometry.nBottomDecoration = pFrame->maGeometry.nLeftDecoration;
4289 int nWidth = aRect.right - aRect.left
4290 - pFrame->maGeometry.nRightDecoration - pFrame->maGeometry.nLeftDecoration;
4291 int nHeight = aRect.bottom - aRect.top
4292 - pFrame->maGeometry.nBottomDecoration - pFrame->maGeometry.nTopDecoration;
4293 // clamp to zero
4294 pFrame->maGeometry.nHeight = nHeight < 0 ? 0 : nHeight;
4295 pFrame->maGeometry.nWidth = nWidth < 0 ? 0 : nWidth;
4296 pFrame->updateScreenNumber();
4299 // -----------------------------------------------------------------------
4301 static void ImplCallMoveHdl( HWND hWnd )
4303 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4304 if ( pFrame )
4306 pFrame->CallCallback( SALEVENT_MOVE, 0 );
4307 // Um doppelte Paints von VCL und SAL zu vermeiden
4308 //if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4309 // UpdateWindow( hWnd );
4313 // -----------------------------------------------------------------------
4315 static void ImplCallClosePopupsHdl( HWND hWnd )
4317 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4318 if ( pFrame )
4320 pFrame->CallCallback( SALEVENT_CLOSEPOPUPS, 0 );
4324 // -----------------------------------------------------------------------
4326 static void ImplHandleMoveMsg( HWND hWnd )
4328 if ( ImplSalYieldMutexTryToAcquire() )
4330 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4331 if ( pFrame )
4333 UpdateFrameGeometry( hWnd, pFrame );
4335 if ( GetWindowStyle( hWnd ) & WS_VISIBLE )
4336 pFrame->mbDefPos = FALSE;
4338 // Gegen moegliche Rekursionen sichern
4339 if ( !pFrame->mbInMoveMsg )
4341 // Fenster im FullScreenModus wieder einpassen
4342 pFrame->mbInMoveMsg = TRUE;
4343 if ( pFrame->mbFullScreen )
4344 ImplSalFrameFullScreenPos( pFrame );
4345 pFrame->mbInMoveMsg = FALSE;
4348 // Status merken
4349 ImplSaveFrameState( pFrame );
4351 // Call Hdl
4352 //#93851 if we call this handler, VCL floating windows are not updated correctly
4353 ImplCallMoveHdl( hWnd );
4357 ImplSalYieldMutexRelease();
4359 else
4360 ImplPostMessage( hWnd, SAL_MSG_POSTMOVE, 0, 0 );
4363 // -----------------------------------------------------------------------
4365 static void ImplCallSizeHdl( HWND hWnd )
4367 // Da Windows diese Messages auch senden kann, muss hier auch die
4368 // Solar-Semaphore beruecksichtigt werden
4369 if ( ImplSalYieldMutexTryToAcquire() )
4371 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4372 if ( pFrame )
4374 pFrame->CallCallback( SALEVENT_RESIZE, 0 );
4375 // Um doppelte Paints von VCL und SAL zu vermeiden
4376 if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4377 UpdateWindow( hWnd );
4380 ImplSalYieldMutexRelease();
4382 else
4383 ImplPostMessage( hWnd, SAL_MSG_POSTCALLSIZE, 0, 0 );
4386 // -----------------------------------------------------------------------
4388 static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
4390 if ( (wParam != SIZE_MAXSHOW) && (wParam != SIZE_MAXHIDE) )
4392 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4393 if ( pFrame )
4395 UpdateFrameGeometry( hWnd, pFrame );
4397 pFrame->mnWidth = (int)LOWORD(lParam);
4398 pFrame->mnHeight = (int)HIWORD(lParam);
4399 // Status merken
4400 ImplSaveFrameState( pFrame );
4401 // Call Hdl
4402 ImplCallSizeHdl( hWnd );
4407 // -----------------------------------------------------------------------
4409 static void ImplHandleFocusMsg( HWND hWnd )
4411 if ( ImplSalYieldMutexTryToAcquire() )
4413 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4414 if ( pFrame && !WinSalFrame::mbInReparent )
4416 // Query the actual status
4417 if ( ::GetFocus() == hWnd )
4419 if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4420 UpdateWindow( hWnd );
4422 // Feststellen, ob wir IME unterstuetzen
4423 if ( pFrame->mbIME && pFrame->mhDefIMEContext )
4425 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
4427 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
4428 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
4429 pFrame->mbHandleIME = !pFrame->mbSpezIME;
4432 pFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
4434 else
4436 pFrame->CallCallback( SALEVENT_LOSEFOCUS, 0 );
4440 ImplSalYieldMutexRelease();
4442 else
4443 ImplPostMessage( hWnd, SAL_MSG_POSTFOCUS, 0, 0 );
4446 // -----------------------------------------------------------------------
4448 static void ImplHandleCloseMsg( HWND hWnd )
4450 if ( ImplSalYieldMutexTryToAcquire() )
4452 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4453 if ( pFrame )
4455 pFrame->CallCallback( SALEVENT_CLOSE, 0 );
4458 ImplSalYieldMutexRelease();
4460 else
4461 ImplPostMessage( hWnd, WM_CLOSE, 0, 0 );
4464 // -----------------------------------------------------------------------
4466 static long ImplHandleShutDownMsg( HWND hWnd )
4468 ImplSalYieldMutexAcquireWithWait();
4469 long nRet = 0;
4470 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4471 if ( pFrame )
4473 nRet = pFrame->CallCallback( SALEVENT_SHUTDOWN, 0 );
4475 ImplSalYieldMutexRelease();
4476 return nRet;
4479 // -----------------------------------------------------------------------
4481 static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg,
4482 WPARAM wParam, LPARAM lParam )
4484 USHORT nSalEvent = SALEVENT_SETTINGSCHANGED;
4486 if ( nMsg == WM_DEVMODECHANGE )
4487 nSalEvent = SALEVENT_PRINTERCHANGED;
4488 else if ( nMsg == WM_DISPLAYCHANGE )
4489 nSalEvent = SALEVENT_DISPLAYCHANGED;
4490 else if ( nMsg == WM_FONTCHANGE )
4491 nSalEvent = SALEVENT_FONTCHANGED;
4492 else if ( nMsg == WM_TIMECHANGE )
4493 nSalEvent = SALEVENT_DATETIMECHANGED;
4494 else if ( nMsg == WM_WININICHANGE )
4496 if ( lParam )
4498 if ( aSalShlData.mbWNT )
4500 if ( ImplSalWICompareAscii( (const wchar_t*)lParam, "devices" ) == 0 )
4501 nSalEvent = SALEVENT_PRINTERCHANGED;
4503 else
4505 if ( stricmp( (const char*)lParam, "devices" ) == 0 )
4506 nSalEvent = SALEVENT_PRINTERCHANGED;
4511 if ( nMsg == WM_SETTINGCHANGE )
4513 if ( wParam == SPI_SETWHEELSCROLLLINES )
4514 aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
4515 else if( wParam == SPI_SETWHEELSCROLLCHARS )
4516 aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars();
4519 if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal )
4520 ImplUpdateSysColorEntries();
4522 ImplSalYieldMutexAcquireWithWait();
4524 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4525 if ( pFrame )
4527 if ( (nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE) )
4529 if ( pFrame->mbFullScreen )
4530 ImplSalFrameFullScreenPos( pFrame );
4533 pFrame->CallCallback( nSalEvent, 0 );
4536 ImplSalYieldMutexRelease();
4539 // -----------------------------------------------------------------------
4541 static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam )
4543 ImplSalYieldMutexAcquireWithWait();
4544 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4545 if ( pFrame )
4547 pFrame->CallCallback( SALEVENT_USEREVENT, (void*)lParam );
4549 ImplSalYieldMutexRelease();
4552 // -----------------------------------------------------------------------
4554 static void ImplHandleForcePalette( HWND hWnd )
4556 SalData* pSalData = GetSalData();
4557 HPALETTE hPal = pSalData->mhDitherPal;
4558 if ( hPal )
4560 if ( !ImplSalYieldMutexTryToAcquire() )
4562 ImplPostMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
4563 return;
4566 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4567 if ( pFrame && pFrame->mpGraphics )
4569 WinSalGraphics* pGraphics = pFrame->mpGraphics;
4570 if ( pGraphics && pGraphics->mhDefPal )
4572 SelectPalette( pGraphics->mhDC, hPal, FALSE );
4573 if ( RealizePalette( pGraphics->mhDC ) )
4575 InvalidateRect( hWnd, NULL, FALSE );
4576 UpdateWindow( hWnd );
4577 pFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
4582 ImplSalYieldMutexRelease();
4586 // -----------------------------------------------------------------------
4588 static LRESULT ImplHandlePalette( BOOL bFrame, HWND hWnd, UINT nMsg,
4589 WPARAM wParam, LPARAM lParam, int& rDef )
4591 SalData* pSalData = GetSalData();
4592 HPALETTE hPal = pSalData->mhDitherPal;
4593 if ( !hPal )
4594 return 0;
4596 rDef = FALSE;
4597 if ( pSalData->mbInPalChange )
4598 return 0;
4600 if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
4602 if ( (HWND)wParam == hWnd )
4603 return 0;
4606 BOOL bReleaseMutex = FALSE;
4607 if ( (nMsg == WM_QUERYNEWPALETTE) || (nMsg == WM_PALETTECHANGED) )
4609 // Da Windows diese Messages auch sendet, muss hier auch die
4610 // Solar-Semaphore beruecksichtigt werden
4611 if ( ImplSalYieldMutexTryToAcquire() )
4612 bReleaseMutex = TRUE;
4613 else if ( nMsg == WM_QUERYNEWPALETTE )
4614 ImplPostMessage( hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam );
4615 else /* ( nMsg == WM_PALETTECHANGED ) */
4616 ImplPostMessage( hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam );
4619 WinSalVirtualDevice*pTempVD;
4620 WinSalFrame* pTempFrame;
4621 WinSalGraphics* pGraphics;
4622 HDC hDC;
4623 HPALETTE hOldPal;
4624 UINT nCols;
4625 BOOL bStdDC;
4626 BOOL bUpdate;
4628 pSalData->mbInPalChange = TRUE;
4630 // Alle Paletten in VirDevs und Frames zuruecksetzen
4631 pTempVD = pSalData->mpFirstVD;
4632 while ( pTempVD )
4634 pGraphics = pTempVD->mpGraphics;
4635 if ( pGraphics->mhDefPal )
4637 SelectPalette( pGraphics->mhDC,
4638 pGraphics->mhDefPal,
4639 TRUE );
4641 pTempVD = pTempVD->mpNext;
4643 pTempFrame = pSalData->mpFirstFrame;
4644 while ( pTempFrame )
4646 pGraphics = pTempFrame->mpGraphics;
4647 if ( pGraphics && pGraphics->mhDefPal )
4649 SelectPalette( pGraphics->mhDC,
4650 pGraphics->mhDefPal,
4651 TRUE );
4653 pTempFrame = pTempFrame->mpNextFrame;
4656 // Palette neu realizen
4657 WinSalFrame* pFrame = NULL;
4658 if ( bFrame )
4659 pFrame = GetWindowPtr( hWnd );
4660 if ( pFrame && pFrame->mpGraphics )
4662 hDC = pFrame->mpGraphics->mhDC;
4663 bStdDC = TRUE;
4665 else
4667 hDC = GetDC( hWnd );
4668 bStdDC = FALSE;
4670 UnrealizeObject( hPal );
4671 hOldPal = SelectPalette( hDC, hPal, TRUE );
4672 nCols = RealizePalette( hDC );
4673 bUpdate = nCols != 0;
4674 if ( !bStdDC )
4676 SelectPalette( hDC, hOldPal, TRUE );
4677 ReleaseDC( hWnd, hDC );
4680 // Alle Paletten in VirDevs und Frames neu setzen
4681 pTempVD = pSalData->mpFirstVD;
4682 while ( pTempVD )
4684 pGraphics = pTempVD->mpGraphics;
4685 if ( pGraphics->mhDefPal )
4687 SelectPalette( pGraphics->mhDC, hPal, TRUE );
4688 RealizePalette( pGraphics->mhDC );
4690 pTempVD = pTempVD->mpNext;
4692 pTempFrame = pSalData->mpFirstFrame;
4693 while ( pTempFrame )
4695 if ( pTempFrame != pFrame )
4697 pGraphics = pTempFrame->mpGraphics;
4698 if ( pGraphics && pGraphics->mhDefPal )
4700 SelectPalette( pGraphics->mhDC, hPal, TRUE );
4701 if ( RealizePalette( pGraphics->mhDC ) )
4702 bUpdate = TRUE;
4705 pTempFrame = pTempFrame->mpNextFrame;
4708 // Wenn sich Farben geaendert haben, dann die Fenster updaten
4709 if ( bUpdate )
4711 pTempFrame = pSalData->mpFirstFrame;
4712 while ( pTempFrame )
4714 pGraphics = pTempFrame->mpGraphics;
4715 if ( pGraphics && pGraphics->mhDefPal )
4717 InvalidateRect( pTempFrame->mhWnd, NULL, FALSE );
4718 UpdateWindow( pTempFrame->mhWnd );
4719 pTempFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
4721 pTempFrame = pTempFrame->mpNextFrame;
4725 pSalData->mbInPalChange = FALSE;
4727 if ( bReleaseMutex )
4728 ImplSalYieldMutexRelease();
4730 if ( nMsg == WM_PALETTECHANGED )
4731 return 0;
4732 else
4733 return nCols;
4736 // -----------------------------------------------------------------------
4738 static int ImplHandleMinMax( HWND hWnd, LPARAM lParam )
4740 int bRet = FALSE;
4742 if ( ImplSalYieldMutexTryToAcquire() )
4744 WinSalFrame* pFrame = GetWindowPtr( hWnd );
4745 if ( pFrame )
4747 MINMAXINFO* pMinMax = (MINMAXINFO*)lParam;
4749 if ( pFrame->mbFullScreen )
4751 int nX;
4752 int nY;
4753 int nDX;
4754 int nDY;
4755 ImplSalCalcFullScreenSize( pFrame, nX, nY, nDX, nDY );
4757 if ( pMinMax->ptMaxPosition.x > nX )
4758 pMinMax->ptMaxPosition.x = nX;
4759 if ( pMinMax->ptMaxPosition.y > nY )
4760 pMinMax->ptMaxPosition.y = nY;
4762 if ( pMinMax->ptMaxSize.x < nDX )
4763 pMinMax->ptMaxSize.x = nDX;
4764 if ( pMinMax->ptMaxSize.y < nDY )
4765 pMinMax->ptMaxSize.y = nDY;
4766 if ( pMinMax->ptMaxTrackSize.x < nDX )
4767 pMinMax->ptMaxTrackSize.x = nDX;
4768 if ( pMinMax->ptMaxTrackSize.y < nDY )
4769 pMinMax->ptMaxTrackSize.y = nDY;
4771 pMinMax->ptMinTrackSize.x = nDX;
4772 pMinMax->ptMinTrackSize.y = nDY;
4774 bRet = TRUE;
4777 if ( pFrame->mnMinWidth || pFrame->mnMinHeight )
4779 int nWidth = pFrame->mnMinWidth;
4780 int nHeight = pFrame->mnMinHeight;
4782 ImplSalAddBorder( pFrame, nWidth, nHeight );
4784 if ( pMinMax->ptMinTrackSize.x < nWidth )
4785 pMinMax->ptMinTrackSize.x = nWidth;
4786 if ( pMinMax->ptMinTrackSize.y < nHeight )
4787 pMinMax->ptMinTrackSize.y = nHeight;
4790 if ( pFrame->mnMaxWidth || pFrame->mnMaxHeight )
4792 int nWidth = pFrame->mnMaxWidth;
4793 int nHeight = pFrame->mnMaxHeight;
4795 ImplSalAddBorder( pFrame, nWidth, nHeight );
4797 if( nWidth > 0 && nHeight > 0 ) // protect against int overflow due to INT_MAX initialisation
4799 if ( pMinMax->ptMaxTrackSize.x > nWidth )
4800 pMinMax->ptMaxTrackSize.x = nWidth;
4801 if ( pMinMax->ptMaxTrackSize.y > nHeight )
4802 pMinMax->ptMaxTrackSize.y = nHeight;
4807 ImplSalYieldMutexRelease();
4810 return bRet;
4813 // -----------------------------------------------------------------------
4815 // retrieves the SalMenuItem pointer from a hMenu
4816 // the pointer is stored in every item, so if no position
4817 // is specified we just use the first item (ie, pos=0)
4818 // if bByPosition is FALSE then nPos denotes a menu id instead of a position
4819 static WinSalMenuItem* ImplGetSalMenuItem( HMENU hMenu, UINT nPos, BOOL bByPosition=TRUE )
4821 DWORD err=0;
4823 MENUITEMINFOW mi;
4824 memset(&mi, 0, sizeof(mi));
4825 mi.cbSize = sizeof( mi );
4826 mi.fMask = MIIM_DATA;
4827 if( !GetMenuItemInfoW( hMenu, nPos, bByPosition, &mi) )
4828 err = GetLastError();
4830 return (WinSalMenuItem *) mi.dwItemData;
4833 // returns the index of the currently selected item if any or -1
4834 static int ImplGetSelectedIndex( HMENU hMenu )
4836 DWORD err=0;
4838 MENUITEMINFOW mi;
4839 memset(&mi, 0, sizeof(mi));
4840 mi.cbSize = sizeof( mi );
4841 mi.fMask = MIIM_STATE;
4842 int n = GetMenuItemCount( hMenu );
4843 if( n != -1 )
4845 for(int i=0; i<n; i++ )
4847 if( !GetMenuItemInfoW( hMenu, i, TRUE, &mi) )
4848 err = GetLastError();
4849 else
4851 if( mi.fState & MFS_HILITE )
4852 return i;
4856 return -1;
4859 static int ImplMenuChar( HWND, WPARAM wParam, LPARAM lParam )
4861 int nRet = MNC_IGNORE;
4862 HMENU hMenu = (HMENU) lParam;
4863 String aMnemonic;
4864 aMnemonic.AssignAscii("&");
4865 aMnemonic.Append( (sal_Unicode) LOWORD(wParam) );
4866 aMnemonic.ToLowerAscii(); // we only have ascii mnemonics
4868 // search the mnemonic in the current menu
4869 int nItemCount = GetMenuItemCount( hMenu );
4870 int nFound = 0;
4871 int idxFound = -1;
4872 int idxSelected = ImplGetSelectedIndex( hMenu );
4873 int idx = idxSelected != -1 ? idxSelected+1 : 0; // if duplicate mnemonics cycle through menu
4874 for( int i=0; i< nItemCount; i++, idx++ )
4876 WinSalMenuItem* pSalMenuItem = ImplGetSalMenuItem( hMenu, idx % nItemCount );
4877 if( !pSalMenuItem )
4878 continue;
4879 String aStr = pSalMenuItem->mText;
4880 aStr.ToLowerAscii();
4881 if( aStr.Search( aMnemonic ) != STRING_NOTFOUND)
4883 if( idxFound == -1 )
4884 idxFound = idx % nItemCount;
4885 if( nFound++ )
4886 break; // duplicate found
4889 if( nFound == 1 )
4890 nRet = MAKELRESULT( idxFound, MNC_EXECUTE );
4891 else
4892 // duplicate mnemonics, just select the next occurence
4893 nRet = MAKELRESULT( idxFound, MNC_SELECT );
4895 return nRet;
4898 static int ImplMeasureItem( HWND hWnd, WPARAM wParam, LPARAM lParam )
4900 int nRet = 0;
4901 if( !wParam )
4903 // request was sent by a menu
4904 nRet = 1;
4905 MEASUREITEMSTRUCT *pMI = (LPMEASUREITEMSTRUCT) lParam;
4906 if( pMI->CtlType != ODT_MENU )
4907 return 0;
4909 WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pMI->itemData;
4910 if( !pSalMenuItem )
4911 return 0;
4913 HDC hdc = GetDC( hWnd );
4914 SIZE strSize;
4916 NONCLIENTMETRICS ncm;
4917 memset( &ncm, 0, sizeof(ncm) );
4918 ncm.cbSize = sizeof( ncm );
4919 SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 );
4921 // Assume every menu item can be default and printed bold
4922 //ncm.lfMenuFont.lfWeight = FW_BOLD;
4924 HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
4926 // menu text and accelerator
4927 String aStr(pSalMenuItem->mText.GetBuffer() );
4928 if( pSalMenuItem->mAccelText.Len() )
4930 aStr.AppendAscii(" ");
4931 aStr.Append( pSalMenuItem->mAccelText );
4933 GetTextExtentPoint32W( hdc, (LPWSTR) aStr.GetBuffer(),
4934 aStr.Len(), &strSize );
4936 // image
4937 Size bmpSize( 16, 16 );
4938 //if( !!pSalMenuItem->maBitmap )
4939 // bmpSize = pSalMenuItem->maBitmap.GetSizePixel();
4941 // checkmark
4942 Size checkSize( GetSystemMetrics( SM_CXMENUCHECK ), GetSystemMetrics( SM_CYMENUCHECK ) );
4944 pMI->itemWidth = checkSize.Width() + 3 + bmpSize.Width() + 3 + strSize.cx;
4945 pMI->itemHeight = Max( Max( checkSize.Height(), bmpSize.Height() ), strSize.cy );
4946 pMI->itemHeight += 4;
4948 DeleteObject( SelectObject(hdc, hfntOld) );
4949 ReleaseDC( hWnd, hdc );
4952 return nRet;
4955 static int ImplDrawItem(HWND, WPARAM wParam, LPARAM lParam )
4957 int nRet = 0;
4958 DWORD err = 0;
4959 if( !wParam )
4961 // request was sent by a menu
4962 nRet = 1;
4963 DRAWITEMSTRUCT *pDI = (LPDRAWITEMSTRUCT) lParam;
4964 if( pDI->CtlType != ODT_MENU )
4965 return 0;
4967 WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pDI->itemData;
4968 if( !pSalMenuItem )
4969 return 0;
4971 COLORREF clrPrevText, clrPrevBkgnd;
4972 HFONT hfntOld;
4973 HBRUSH hbrOld;
4974 BOOL fChecked = (pDI->itemState & ODS_CHECKED) ? TRUE : FALSE;
4975 BOOL fSelected = (pDI->itemState & ODS_SELECTED) ? TRUE : FALSE;
4976 BOOL fDisabled = (pDI->itemState & (ODS_DISABLED | ODS_GRAYED)) ? TRUE : FALSE;
4978 // Set the appropriate foreground and background colors.
4979 RECT aRect = pDI->rcItem;
4981 clrPrevBkgnd = SetBkColor( pDI->hDC, GetSysColor( COLOR_MENU ) );
4983 if ( fDisabled )
4984 clrPrevText = SetTextColor( pDI->hDC, GetSysColor( COLOR_GRAYTEXT ) );
4985 else
4986 clrPrevText = SetTextColor( pDI->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
4988 DWORD colBackground = GetSysColor( fSelected ? COLOR_HIGHLIGHT : COLOR_MENU );
4989 if ( fSelected )
4990 clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground );
4991 else
4992 clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground );
4994 hbrOld = (HBRUSH)SelectObject( pDI->hDC, CreateSolidBrush( GetBkColor( pDI->hDC ) ) );
4996 // Fill background
4997 if(!PatBlt( pDI->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY ))
4998 err = GetLastError();
5000 int lineHeight = aRect.bottom-aRect.top;
5002 int x = aRect.left;
5003 int y = aRect.top;
5005 int checkWidth = GetSystemMetrics( SM_CXMENUCHECK );
5006 int checkHeight = GetSystemMetrics( SM_CYMENUCHECK );
5007 if( fChecked )
5009 RECT r;
5010 r.left = 0;
5011 r.top = 0;
5012 r.right = checkWidth;
5013 r.bottom = checkWidth;
5014 HDC memDC = CreateCompatibleDC( pDI->hDC );
5015 HBITMAP memBmp = CreateCompatibleBitmap( pDI->hDC, checkWidth, checkHeight );
5016 HBITMAP hOldBmp = (HBITMAP) SelectObject( memDC, memBmp );
5017 DrawFrameControl( memDC, &r, DFC_MENU, DFCS_MENUCHECK );
5018 BitBlt( pDI->hDC, x, y+(lineHeight-checkHeight)/2, checkWidth, checkHeight, memDC, 0, 0, SRCAND );
5019 DeleteObject( SelectObject( memDC, hOldBmp ) );
5020 DeleteDC( memDC );
5022 x += checkWidth+3;
5024 //Size bmpSize = aBitmap.GetSizePixel();
5025 Size bmpSize(16, 16);
5026 if( !!pSalMenuItem->maBitmap )
5028 Bitmap aBitmap( pSalMenuItem->maBitmap );
5030 // set transparent pixels to background color
5031 if( fDisabled )
5032 colBackground = RGB(255,255,255);
5033 aBitmap.Replace( Color( COL_LIGHTMAGENTA ),
5034 Color( GetRValue(colBackground),GetGValue(colBackground),GetBValue(colBackground) ), 0);
5036 WinSalBitmap* pSalBmp = static_cast<WinSalBitmap*>(aBitmap.ImplGetImpBitmap()->ImplGetSalBitmap());
5037 HGLOBAL hDrawDIB = pSalBmp->ImplGethDIB();
5039 if( hDrawDIB )
5041 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDrawDIB );
5042 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI;
5043 PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI +
5044 pSalBmp->ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD );
5046 HBITMAP hBmp = CreateDIBitmap( pDI->hDC, pBIH, CBM_INIT, pBits, pBI, DIB_RGB_COLORS );
5047 GlobalUnlock( hDrawDIB );
5049 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
5050 DrawStateW( pDI->hDC, (HBRUSH)hbrIcon, (DRAWSTATEPROC)NULL, (LPARAM)hBmp, (WPARAM)0,
5051 x, y+(lineHeight-bmpSize.Height())/2, bmpSize.Width(), bmpSize.Height(),
5052 DST_BITMAP | (fDisabled ? (fSelected ? DSS_MONO : DSS_DISABLED) : DSS_NORMAL) );
5054 DeleteObject( hbrIcon );
5055 DeleteObject( hBmp );
5059 x += bmpSize.Width() + 3;
5060 aRect.left = x;
5062 NONCLIENTMETRICS ncm;
5063 memset( &ncm, 0, sizeof(ncm) );
5064 ncm.cbSize = sizeof( ncm );
5065 SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 );
5067 // Print default menu entry with bold font
5068 //if ( pDI->itemState & ODS_DEFAULT )
5069 // ncm.lfMenuFont.lfWeight = FW_BOLD;
5071 hfntOld = (HFONT) SelectObject(pDI->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
5073 SIZE strSize;
5074 String aStr( pSalMenuItem->mText.GetBuffer() );
5075 GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(),
5076 aStr.Len(), &strSize );
5078 if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL,
5079 (LPARAM)(LPWSTR) aStr.GetBuffer(),
5080 (WPARAM)0, aRect.left, aRect.top + (lineHeight - strSize.cy)/2, 0, 0,
5081 DST_PREFIXTEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) )
5082 err = GetLastError();
5084 if( pSalMenuItem->mAccelText.Len() )
5086 SIZE strSizeA;
5087 aStr = pSalMenuItem->mAccelText;
5088 GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(),
5089 aStr.Len(), &strSizeA );
5090 TEXTMETRIC tm;
5091 GetTextMetrics( pDI->hDC, &tm );
5093 // position the accelerator string to the right but leave space for the
5094 // (potential) submenu arrow (tm.tmMaxCharWidth)
5095 if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL,
5096 (LPARAM)(LPWSTR) aStr.GetBuffer(),
5097 (WPARAM)0, aRect.right-strSizeA.cx-tm.tmMaxCharWidth, aRect.top + (lineHeight - strSizeA.cy)/2, 0, 0,
5098 DST_TEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) )
5099 err = GetLastError();
5102 // Restore the original font and colors.
5103 DeleteObject( SelectObject( pDI->hDC, hbrOld ) );
5104 DeleteObject( SelectObject( pDI->hDC, hfntOld) );
5105 SetTextColor(pDI->hDC, clrPrevText);
5106 SetBkColor(pDI->hDC, clrPrevBkgnd);
5108 return nRet;
5111 static int ImplHandleMenuActivate( HWND hWnd, WPARAM wParam, LPARAM )
5113 // Menu activation
5114 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5115 if ( !pFrame )
5116 return 0;
5118 HMENU hMenu = (HMENU) wParam;
5119 // WORD nPos = LOWORD (lParam);
5120 // BOOL bWindowMenu = (BOOL) HIWORD(lParam);
5122 // Send activate and deactivate together, so we have not keep track of opened menues
5123 // this will be enough to have the menues updated correctly
5124 SalMenuEvent aMenuEvt;
5125 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, 0 );
5126 if( pSalMenuItem )
5127 aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5128 else
5129 aMenuEvt.mpMenu = NULL;
5131 long nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt );
5132 if( nRet )
5133 nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt );
5134 if( nRet )
5135 pFrame->mLastActivatedhMenu = hMenu;
5137 return (nRet!=0);
5140 static int ImplHandleMenuSelect( HWND hWnd, WPARAM wParam, LPARAM lParam )
5142 // Menu selection
5143 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5144 if ( !pFrame )
5145 return 0;
5147 WORD nId = LOWORD(wParam); // menu item or submenu index
5148 WORD nFlags = HIWORD(wParam);
5149 HMENU hMenu = (HMENU) lParam;
5151 // check if we have to process the message
5152 if( !GetSalData()->IsKnownMenuHandle( hMenu ) )
5153 return 0;
5155 BOOL bByPosition = FALSE;
5156 if( nFlags & MF_POPUP )
5157 bByPosition = TRUE;
5159 long nRet = 0;
5160 if ( hMenu && !pFrame->mLastActivatedhMenu )
5162 // we never activated a menu (ie, no WM_INITMENUPOPUP has occured yet)
5163 // which means this must be the menubar -> send activation/deactivation
5164 SalMenuEvent aMenuEvt;
5165 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, bByPosition );
5166 if( pSalMenuItem )
5167 aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5168 else
5169 aMenuEvt.mpMenu = NULL;
5171 nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt );
5172 if( nRet )
5173 nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt );
5174 if( nRet )
5175 pFrame->mLastActivatedhMenu = hMenu;
5178 if( !hMenu && nFlags == 0xFFFF )
5180 // all menus are closed, reset activation logic
5181 pFrame->mLastActivatedhMenu = NULL;
5184 if( hMenu )
5186 // hMenu must be saved, as it is not passed in WM_COMMAND which always occurs after a selection
5187 // if a menu is closed due to a command selection then hMenu is NULL, but WM_COMMAND comes later
5188 // so we must not overwrite it in this case
5189 pFrame->mSelectedhMenu = hMenu;
5191 // send highlight event
5192 if( nFlags & MF_POPUP )
5194 // submenu selected
5195 // wParam now carries an index instead of an id -> retrieve id
5196 MENUITEMINFOW mi;
5197 memset(&mi, 0, sizeof(mi));
5198 mi.cbSize = sizeof( mi );
5199 mi.fMask = MIIM_ID;
5200 if( GetMenuItemInfoW( hMenu, LOWORD(wParam), TRUE, &mi) )
5201 nId = sal::static_int_cast<WORD>(mi.wID);
5204 SalMenuEvent aMenuEvt;
5205 aMenuEvt.mnId = nId;
5206 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, FALSE );
5207 if( pSalMenuItem )
5208 aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5209 else
5210 aMenuEvt.mpMenu = NULL;
5212 nRet = pFrame->CallCallback( SALEVENT_MENUHIGHLIGHT, &aMenuEvt );
5215 return (nRet != 0);
5218 static int ImplHandleCommand( HWND hWnd, WPARAM wParam, LPARAM )
5220 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5221 if ( !pFrame )
5222 return 0;
5224 long nRet = 0;
5225 if( !HIWORD(wParam) )
5227 // Menu command
5228 WORD nId = LOWORD(wParam);
5229 if( nId ) // zero for separators
5231 SalMenuEvent aMenuEvt;
5232 aMenuEvt.mnId = nId;
5233 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( pFrame->mSelectedhMenu, nId, FALSE );
5234 if( pSalMenuItem )
5235 aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5236 else
5237 aMenuEvt.mpMenu = NULL;
5239 nRet = pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt );
5242 return (nRet != 0);
5245 static int ImplHandleSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
5247 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5248 if ( !pFrame )
5249 return 0;
5251 WPARAM nCommand = wParam & 0xFFF0;
5253 if ( pFrame->mbFullScreen )
5255 WIN_BOOL bMaximize = IsZoomed( pFrame->mhWnd );
5256 WIN_BOOL bMinimize = IsIconic( pFrame->mhWnd );
5257 if ( (nCommand == SC_SIZE) ||
5258 (!bMinimize && (nCommand == SC_MOVE)) ||
5259 (!bMaximize && (nCommand == SC_MAXIMIZE)) ||
5260 (bMaximize && (nCommand == SC_RESTORE)) )
5262 MessageBeep( 0 );
5263 return TRUE;
5267 if ( nCommand == SC_KEYMENU )
5269 // do not process SC_KEYMENU if we have a native menu
5270 // Windows should handle this
5271 if( GetMenu( hWnd ) )
5272 return FALSE;
5274 // Hier verarbeiten wir nur KeyMenu-Events fuer Alt um
5275 // den MenuBar zu aktivieren, oder wenn ein SysChild-Fenster
5276 // den Focus hat, da diese Alt+Tasten-Kombinationen nur
5277 // ueber diesen Event verarbeitet werden
5278 if ( !LOWORD( lParam ) )
5280 // Nur ausloesen, wenn keine weitere Taste gedrueckt ist. Im
5281 // Gegensatz zur Doku wird in der X-Koordinaate der CharCode
5282 // geliefert, der zusaetzlich gedrueckt ist
5283 // Also 32 fuer Space, 99 fuer c, 100 fuer d, ...
5284 // Da dies nicht dokumentiert ist, fragen wir vorsichtshalber
5285 // auch den Status der Space-Taste ab
5286 if ( GetKeyState( VK_SPACE ) & 0x8000 )
5287 return 0;
5289 // Damit nicht bei Alt+Maustaste auch der MenuBar aktiviert wird
5290 if ( (GetKeyState( VK_LBUTTON ) & 0x8000) ||
5291 (GetKeyState( VK_RBUTTON ) & 0x8000) ||
5292 (GetKeyState( VK_MBUTTON ) & 0x8000) ||
5293 (GetKeyState( VK_SHIFT ) & 0x8000) )
5294 return 1;
5296 SalKeyEvent aKeyEvt;
5297 aKeyEvt.mnTime = GetMessageTime();
5298 aKeyEvt.mnCode = KEY_MENU;
5299 aKeyEvt.mnCharCode = 0;
5300 aKeyEvt.mnRepeat = 0;
5301 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
5302 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
5303 return (nRet != 0);
5305 else
5307 // Testen, ob ein SysChild den Focus hat
5308 HWND hFocusWnd = ::GetFocus();
5309 if ( hFocusWnd && ImplFindSalObject( hFocusWnd ) )
5311 char cKeyCode = (char)(unsigned char)LOWORD( lParam );
5312 // LowerCase
5313 if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
5314 cKeyCode += 32;
5315 // Wir nehmen nur 0-9 und A-Z, alle anderen Tasten muessen durch
5316 // den Hook vom SalObj verarbeitet werden
5317 if ( ((cKeyCode >= 48) && (cKeyCode <= 57)) ||
5318 ((cKeyCode >= 97) && (cKeyCode <= 122)) )
5320 USHORT nModCode = 0;
5321 if ( GetKeyState( VK_SHIFT ) & 0x8000 )
5322 nModCode |= KEY_SHIFT;
5323 if ( GetKeyState( VK_CONTROL ) & 0x8000 )
5324 nModCode |= KEY_MOD1;
5325 nModCode |= KEY_MOD2;
5327 SalKeyEvent aKeyEvt;
5328 aKeyEvt.mnTime = GetMessageTime();
5329 if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
5330 aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
5331 else
5332 aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
5333 aKeyEvt.mnCode |= nModCode;
5334 aKeyEvt.mnCharCode = cKeyCode;
5335 aKeyEvt.mnRepeat = 0;
5336 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
5337 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
5338 return (nRet != 0);
5344 return FALSE;
5347 // -----------------------------------------------------------------------
5349 static void ImplHandleInputLangChange( HWND hWnd, WPARAM, LPARAM lParam )
5351 ImplSalYieldMutexAcquireWithWait();
5353 // Feststellen, ob wir IME unterstuetzen
5354 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5355 if ( pFrame && pFrame->mbIME && pFrame->mhDefIMEContext )
5357 HKL hKL = (HKL)lParam;
5358 UINT nImeProps = ImmGetProperty( hKL, IGP_PROPERTY );
5360 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
5361 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
5362 pFrame->mbHandleIME = !pFrame->mbSpezIME;
5365 // trigger input language and codepage update
5366 UINT nLang = pFrame->mnInputLang;
5367 ImplUpdateInputLang( pFrame );
5369 // notify change
5370 if( nLang != pFrame->mnInputLang )
5371 pFrame->CallCallback( SALEVENT_INPUTLANGUAGECHANGE, 0 );
5373 ImplSalYieldMutexRelease();
5376 // -----------------------------------------------------------------------
5378 static void ImplUpdateIMECursorPos( WinSalFrame* pFrame, HIMC hIMC )
5380 COMPOSITIONFORM aForm;
5381 memset( &aForm, 0, sizeof( aForm ) );
5383 // Cursor-Position ermitteln und aus der die Default-Position fuer
5384 // das Composition-Fenster berechnen
5385 SalExtTextInputPosEvent aPosEvt;
5386 pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
5387 if ( (aPosEvt.mnX == -1) && (aPosEvt.mnY == -1) )
5388 aForm.dwStyle |= CFS_DEFAULT;
5389 else
5391 aForm.dwStyle |= CFS_POINT;
5392 aForm.ptCurrentPos.x = aPosEvt.mnX;
5393 aForm.ptCurrentPos.y = aPosEvt.mnY;
5395 ImmSetCompositionWindow( hIMC, &aForm );
5397 // Because not all IME's use this values, we create
5398 // a Windows caret to force the Position from the IME
5399 if ( GetFocus() == pFrame->mhWnd )
5401 CreateCaret( pFrame->mhWnd, 0,
5402 aPosEvt.mnWidth, aPosEvt.mnHeight );
5403 SetCaretPos( aPosEvt.mnX, aPosEvt.mnY );
5407 // -----------------------------------------------------------------------
5409 static BOOL ImplHandleIMEStartComposition( HWND hWnd )
5411 BOOL bDef = TRUE;
5413 ImplSalYieldMutexAcquireWithWait();
5415 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5416 if ( pFrame )
5418 HIMC hIMC = ImmGetContext( hWnd );
5419 if ( hIMC )
5421 ImplUpdateIMECursorPos( pFrame, hIMC );
5422 ImmReleaseContext( hWnd, hIMC );
5425 if ( pFrame->mbHandleIME )
5427 if ( pFrame->mbAtCursorIME )
5428 bDef = FALSE;
5432 ImplSalYieldMutexRelease();
5434 return bDef;
5437 // -----------------------------------------------------------------------
5439 static BOOL ImplHandleIMECompositionInput( WinSalFrame* pFrame,
5440 HIMC hIMC, LPARAM lParam )
5442 BOOL bDef = TRUE;
5444 // Init Event
5445 SalExtTextInputEvent aEvt;
5446 aEvt.mnTime = GetMessageTime();
5447 aEvt.mpTextAttr = NULL;
5448 aEvt.mnCursorPos = 0;
5449 aEvt.mnDeltaStart = 0;
5450 aEvt.mbOnlyCursor = FALSE;
5451 aEvt.mnCursorFlags = 0;
5453 // If we get a result string, then we handle this input
5454 if ( lParam & GCS_RESULTSTR )
5456 bDef = FALSE;
5458 LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, 0, 0 ) / sizeof( WCHAR );
5459 if ( nTextLen >= 0 )
5461 WCHAR* pTextBuf = new WCHAR[nTextLen];
5462 ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
5463 aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen );
5464 delete pTextBuf;
5467 aEvt.mnCursorPos = aEvt.maText.Len();
5468 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5469 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5470 ImplUpdateIMECursorPos( pFrame, hIMC );
5473 // If the IME doesn't support OnSpot input, then there is nothing to do
5474 if ( !pFrame->mbAtCursorIME )
5475 return !bDef;
5477 // If we get new Composition data, then we handle this new input
5478 if ( (lParam & (GCS_COMPSTR | GCS_COMPATTR)) ||
5479 ((lParam & GCS_CURSORPOS) && !(lParam & GCS_RESULTSTR)) )
5481 bDef = FALSE;
5483 USHORT* pSalAttrAry = NULL;
5484 LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ) / sizeof( WCHAR );
5485 if ( nTextLen > 0 )
5487 WCHAR* pTextBuf = new WCHAR[nTextLen];
5488 ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
5489 aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen );
5490 delete pTextBuf;
5492 WIN_BYTE* pAttrBuf = NULL;
5493 LONG nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, 0, 0 );
5494 if ( nAttrLen > 0 )
5496 pAttrBuf = new WIN_BYTE[nAttrLen];
5497 ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf, nAttrLen );
5500 if ( pAttrBuf )
5502 xub_StrLen nTextLen = aEvt.maText.Len();
5503 pSalAttrAry = new USHORT[nTextLen];
5504 memset( pSalAttrAry, 0, nTextLen*sizeof( USHORT ) );
5505 for ( xub_StrLen i = 0; (i < nTextLen) && (i < nAttrLen); i++ )
5507 WIN_BYTE nWinAttr = pAttrBuf[i];
5508 USHORT nSalAttr;
5509 if ( nWinAttr == ATTR_TARGET_CONVERTED )
5511 nSalAttr = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
5512 aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
5514 else if ( nWinAttr == ATTR_CONVERTED )
5515 nSalAttr = SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE;
5516 else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED )
5517 nSalAttr = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
5518 else if ( nWinAttr == ATTR_INPUT_ERROR )
5519 nSalAttr = SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
5520 else /* ( nWinAttr == ATTR_INPUT ) */
5521 nSalAttr = SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
5522 pSalAttrAry[i] = nSalAttr;
5525 aEvt.mpTextAttr = pSalAttrAry;
5526 delete pAttrBuf;
5530 // Only when we get new composition data, we must send this event
5531 if ( (nTextLen > 0) || !(lParam & GCS_RESULTSTR) )
5533 // End the mode, if the last character is deleted
5534 if ( !nTextLen && !pFrame->mbCandidateMode )
5536 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5537 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5539 else
5541 // Because Cursor-Position and DeltaStart never updated
5542 // from the korean input engine, we must handle this here
5543 if ( lParam & CS_INSERTCHAR )
5545 aEvt.mnCursorPos = nTextLen;
5546 if ( aEvt.mnCursorPos && (lParam & CS_NOMOVECARET) )
5547 aEvt.mnCursorPos--;
5549 else
5550 aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, 0, 0 ) );
5552 if ( pFrame->mbCandidateMode )
5553 aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
5554 if ( lParam & CS_NOMOVECARET )
5555 aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_OVERWRITE;
5557 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5559 ImplUpdateIMECursorPos( pFrame, hIMC );
5562 if ( pSalAttrAry )
5563 delete pSalAttrAry;
5566 return !bDef;
5569 // -----------------------------------------------------------------------
5571 static BOOL ImplHandleIMEComposition( HWND hWnd, LPARAM lParam )
5573 BOOL bDef = TRUE;
5574 ImplSalYieldMutexAcquireWithWait();
5576 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5577 if ( pFrame && (!lParam || (lParam & GCS_RESULTSTR)) )
5579 // Wir restaurieren den Background-Modus bei jeder Texteingabe,
5580 // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
5581 if ( pFrame->mpGraphics &&
5582 pFrame->mpGraphics->mhDC )
5583 SetBkMode( pFrame->mpGraphics->mhDC, TRANSPARENT );
5586 if ( pFrame && pFrame->mbHandleIME )
5588 if ( !lParam )
5590 SalExtTextInputEvent aEvt;
5591 aEvt.mnTime = GetMessageTime();
5592 aEvt.mpTextAttr = NULL;
5593 aEvt.mnCursorPos = 0;
5594 aEvt.mnDeltaStart = 0;
5595 aEvt.mbOnlyCursor = FALSE;
5596 aEvt.mnCursorFlags = 0;
5597 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5598 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5600 else if ( lParam & (GCS_RESULTSTR | GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) )
5602 HIMC hIMC = ImmGetContext( hWnd );
5603 if ( hIMC )
5605 if ( ImplHandleIMECompositionInput( pFrame, hIMC, lParam ) )
5606 bDef = FALSE;
5608 ImmReleaseContext( hWnd, hIMC );
5613 ImplSalYieldMutexRelease();
5614 return bDef;
5617 // -----------------------------------------------------------------------
5619 static BOOL ImplHandleIMEEndComposition( HWND hWnd )
5621 BOOL bDef = TRUE;
5623 ImplSalYieldMutexAcquireWithWait();
5625 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5626 if ( pFrame && pFrame->mbHandleIME )
5628 if ( pFrame->mbAtCursorIME )
5629 bDef = FALSE;
5632 ImplSalYieldMutexRelease();
5634 return bDef;
5637 // -----------------------------------------------------------------------
5639 static boolean ImplHandleAppCommand( HWND hWnd, LPARAM lParam )
5641 sal_Int16 nCommand = 0;
5642 switch( GET_APPCOMMAND_LPARAM(lParam) )
5644 case APPCOMMAND_MEDIA_CHANNEL_DOWN: nCommand = MEDIA_COMMAND_CHANNEL_DOWN; break;
5645 case APPCOMMAND_MEDIA_CHANNEL_UP: nCommand = MEDIA_COMMAND_CHANNEL_UP; break;
5646 case APPCOMMAND_MEDIA_NEXTTRACK: nCommand = MEDIA_COMMAND_NEXTTRACK; break;
5647 case APPCOMMAND_MEDIA_PAUSE: nCommand = MEDIA_COMMAND_PAUSE; break;
5648 case APPCOMMAND_MEDIA_PLAY: nCommand = MEDIA_COMMAND_PLAY; break;
5649 case APPCOMMAND_MEDIA_PLAY_PAUSE: nCommand = MEDIA_COMMAND_PLAY_PAUSE; break;
5650 case APPCOMMAND_MEDIA_PREVIOUSTRACK: nCommand = MEDIA_COMMAND_PREVIOUSTRACK; break;
5651 case APPCOMMAND_MEDIA_RECORD: nCommand = MEDIA_COMMAND_RECORD; break;
5652 case APPCOMMAND_MEDIA_REWIND: nCommand = MEDIA_COMMAND_REWIND; break;
5653 case APPCOMMAND_MEDIA_STOP: nCommand = MEDIA_COMMAND_STOP; break;
5654 case APPCOMMAND_MIC_ON_OFF_TOGGLE: nCommand = MEDIA_COMMAND_MIC_ON_OFF_TOGGLE; break;
5655 case APPCOMMAND_MICROPHONE_VOLUME_DOWN: nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_DOWN; break;
5656 case APPCOMMAND_MICROPHONE_VOLUME_MUTE: nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_MUTE; break;
5657 case APPCOMMAND_MICROPHONE_VOLUME_UP: nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_UP; break;
5658 case APPCOMMAND_VOLUME_DOWN: nCommand = MEDIA_COMMAND_VOLUME_DOWN; break;
5659 case APPCOMMAND_VOLUME_MUTE: nCommand = MEDIA_COMMAND_VOLUME_MUTE; break;
5660 case APPCOMMAND_VOLUME_UP: nCommand = MEDIA_COMMAND_VOLUME_UP; break;
5661 break;
5662 default:
5663 return false;
5666 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5667 Window *pWindow = pFrame ? pFrame->GetWindow() : NULL;
5669 if( pWindow )
5671 const Point aPoint;
5672 CommandEvent aCEvt( aPoint, COMMAND_MEDIA, FALSE, &nCommand );
5673 NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
5675 if ( !ImplCallPreNotify( aNCmdEvt ) )
5677 pWindow->Command( aCEvt );
5678 return true;
5682 return false;
5686 static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam )
5688 if ( wParam == (WPARAM)IMN_OPENCANDIDATE )
5690 ImplSalYieldMutexAcquireWithWait();
5692 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5693 if ( pFrame && pFrame->mbHandleIME &&
5694 pFrame->mbAtCursorIME )
5696 // Wir wollen den Cursor hiden
5697 pFrame->mbCandidateMode = TRUE;
5698 ImplHandleIMEComposition( hWnd, GCS_CURSORPOS );
5700 HWND hWnd = pFrame->mhWnd;
5701 HIMC hIMC = ImmGetContext( hWnd );
5702 if ( hIMC )
5704 LONG nBufLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 );
5705 if ( nBufLen >= 1 )
5707 SalExtTextInputPosEvent aPosEvt;
5708 pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
5710 // Vertical !!!
5711 CANDIDATEFORM aForm;
5712 aForm.dwIndex = 0;
5713 aForm.dwStyle = CFS_EXCLUDE;
5714 aForm.ptCurrentPos.x = aPosEvt.mnX;
5715 aForm.ptCurrentPos.y = aPosEvt.mnY+1;
5716 aForm.rcArea.left = aPosEvt.mnX;
5717 aForm.rcArea.top = aPosEvt.mnY;
5718 aForm.rcArea.right = aForm.rcArea.left+aPosEvt.mnExtWidth+1;
5719 aForm.rcArea.bottom = aForm.rcArea.top+aPosEvt.mnHeight+1;
5720 ImmSetCandidateWindow( hIMC, &aForm );
5723 ImmReleaseContext( hWnd, hIMC );
5727 ImplSalYieldMutexRelease();
5729 else if ( wParam == (WPARAM)IMN_CLOSECANDIDATE )
5731 ImplSalYieldMutexAcquireWithWait();
5732 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5733 if ( pFrame )
5734 pFrame->mbCandidateMode = FALSE;
5735 ImplSalYieldMutexRelease();
5739 // -----------------------------------------------------------------------
5740 #if WINVER >= 0x0500
5742 static LRESULT ImplHandleIMEReconvertString( HWND hWnd, LPARAM lParam )
5744 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5745 LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam;
5746 LRESULT nRet = 0;
5747 SalSurroundingTextRequestEvent aEvt;
5748 aEvt.maText = UniString();
5749 aEvt.mnStart = aEvt.mnEnd = 0;
5751 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_SETCOMPSTR );
5752 if( (nImeProps & SCS_CAP_SETRECONVERTSTRING) == 0 )
5754 // This IME does not support reconversion.
5755 return 0;
5758 if( !pReconvertString )
5760 // The first call for reconversion.
5761 pFrame->CallCallback( SALEVENT_STARTRECONVERSION, (void*)NULL );
5763 // Retrieve the surrounding text from the focused control.
5764 pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5766 if( aEvt.maText.Len() == 0 )
5768 return 0;
5771 nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR);
5773 else
5775 // The second call for reconversion.
5777 // Retrieve the surrounding text from the focused control.
5778 pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5779 nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR);
5781 pReconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
5782 pReconvertString->dwStrLen = aEvt.maText.Len();
5783 pReconvertString->dwCompStrOffset = aEvt.mnStart * sizeof(WCHAR);
5784 pReconvertString->dwCompStrLen = aEvt.mnEnd - aEvt.mnStart;
5785 pReconvertString->dwTargetStrOffset = pReconvertString->dwCompStrOffset;
5786 pReconvertString->dwTargetStrLen = pReconvertString->dwCompStrLen;
5788 memcpy( (LPWSTR)(pReconvertString + 1), aEvt.maText.GetBuffer(), (aEvt.maText.Len() + 1) * sizeof(WCHAR) );
5791 // just return the required size of buffer to reconvert.
5792 return nRet;
5795 // -----------------------------------------------------------------------
5797 static LRESULT ImplHandleIMEConfirmReconvertString( HWND hWnd, LPARAM lParam )
5799 WinSalFrame* pFrame = GetWindowPtr( hWnd );
5800 LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam;
5801 SalSurroundingTextRequestEvent aEvt;
5802 aEvt.maText = UniString();
5803 aEvt.mnStart = aEvt.mnEnd = 0;
5805 pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5807 ULONG nTmpStart = pReconvertString->dwCompStrOffset / sizeof(WCHAR);
5808 ULONG nTmpEnd = nTmpStart + pReconvertString->dwCompStrLen;
5810 if( nTmpStart != aEvt.mnStart || nTmpEnd != aEvt.mnEnd )
5812 SalSurroundingTextSelectionChangeEvent aSelEvt;
5813 aSelEvt.mnStart = nTmpStart;
5814 aSelEvt.mnEnd = nTmpEnd;
5816 pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTSELECTIONCHANGE, (void*)&aSelEvt );
5819 return TRUE;
5822 #endif // WINVER >= 0x0500
5824 // -----------------------------------------------------------------------
5826 void SalTestMouseLeave()
5828 SalData* pSalData = GetSalData();
5830 if ( pSalData->mhWantLeaveMsg && !::GetCapture() )
5832 POINT aPt;
5833 GetCursorPos( &aPt );
5834 if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) )
5835 ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) );
5839 // -----------------------------------------------------------------------
5841 static int ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ,
5842 LRESULT& rResult )
5844 POINT aPt;
5845 POINT aScreenPt;
5846 aScreenPt.x = (short)LOWORD( lParam );
5847 aScreenPt.y = (short)HIWORD( lParam );
5848 // Child-Fenster suchen, welches an der entsprechenden
5849 // Position liegt
5850 HWND hChildWnd;
5851 HWND hWheelWnd = hWnd;
5854 hChildWnd = hWheelWnd;
5855 aPt = aScreenPt;
5856 ScreenToClient( hChildWnd, &aPt );
5857 hWheelWnd = ChildWindowFromPointEx( hChildWnd, aPt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT );
5859 while ( hWheelWnd && (hWheelWnd != hChildWnd) );
5860 if ( hWheelWnd && (hWheelWnd != hWnd) &&
5861 (hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) )
5863 rResult = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
5864 return FALSE;
5867 return TRUE;
5870 // -----------------------------------------------------------------------
5872 LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
5874 LRESULT nRet = 0;
5875 static int bInWheelMsg = FALSE;
5876 static int bInQueryEnd = FALSE;
5878 // By WM_CRETAE we connect the frame with the window handle
5879 if ( nMsg == WM_CREATE )
5881 // Window-Instanz am Windowhandle speichern
5882 // Can also be used for the W-Version, because the struct
5883 // to access lpCreateParams is the same structure
5884 CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam;
5885 WinSalFrame* pFrame = (WinSalFrame*)pStruct->lpCreateParams;
5886 if ( pFrame != 0 )
5888 SetWindowPtr( hWnd, pFrame );
5889 // HWND schon hier setzen, da schon auf den Instanzdaten
5890 // gearbeitet werden kann, wenn Messages waehrend
5891 // CreateWindow() gesendet werden
5892 pFrame->mhWnd = hWnd;
5893 pFrame->maSysData.hWnd = hWnd;
5895 return 0;
5898 ImplSVData* pSVData = ImplGetSVData();
5899 // #i72707# TODO: the mbDeInit check will not be needed
5900 // once all windows that are not properly closed on exit got fixed
5901 if( pSVData->mbDeInit )
5902 return 0;
5904 if ( WM_USER_SYSTEM_WINDOW_ACTIVATED == nMsg )
5906 if (pSVData->mpIntroWindow)
5907 pSVData->mpIntroWindow->Hide();
5909 return 0;
5912 bool bCheckTimers = false;
5914 switch( nMsg )
5916 case WM_MOUSEMOVE:
5917 case WM_LBUTTONDOWN:
5918 case WM_MBUTTONDOWN:
5919 case WM_RBUTTONDOWN:
5920 case WM_LBUTTONUP:
5921 case WM_MBUTTONUP:
5922 case WM_RBUTTONUP:
5923 case WM_NCMOUSEMOVE:
5924 case SAL_MSG_MOUSELEAVE:
5925 ImplSalYieldMutexAcquireWithWait();
5926 rDef = !ImplHandleMouseMsg( hWnd, nMsg, wParam, lParam );
5927 ImplSalYieldMutexRelease();
5928 break;
5930 case WM_NCLBUTTONDOWN:
5931 case WM_NCMBUTTONDOWN:
5932 case WM_NCRBUTTONDOWN:
5933 ImplSalYieldMutexAcquireWithWait();
5934 ImplCallClosePopupsHdl( hWnd ); // close popups...
5935 ImplSalYieldMutexRelease();
5936 break;
5938 case WM_MOUSEACTIVATE:
5939 if ( LOWORD( lParam ) == HTCLIENT )
5941 ImplSalYieldMutexAcquireWithWait();
5942 nRet = ImplHandleMouseActivateMsg( hWnd );
5943 ImplSalYieldMutexRelease();
5944 if ( nRet )
5946 nRet = MA_NOACTIVATE;
5947 rDef = FALSE;
5950 break;
5952 case WM_KEYDOWN:
5953 case WM_KEYUP:
5954 case WM_DEADCHAR:
5955 case WM_CHAR:
5956 case WM_UNICHAR: // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0
5957 case WM_SYSKEYDOWN:
5958 case WM_SYSKEYUP:
5959 case WM_SYSCHAR:
5960 ImplSalYieldMutexAcquireWithWait();
5961 rDef = !ImplHandleKeyMsg( hWnd, nMsg, wParam, lParam, nRet );
5962 ImplSalYieldMutexRelease();
5963 break;
5965 case WM_MOUSEWHEEL:
5966 // FALLTHROUGH intended
5967 case WM_MOUSEHWHEEL:
5968 // Gegen Rekursion absichern, falls wir vom IE oder dem externen
5969 // Fenster die Message wieder zurueckbekommen
5970 if ( !bInWheelMsg )
5972 bInWheelMsg++;
5973 rDef = !ImplHandleWheelMsg( hWnd, nMsg, wParam, lParam );
5974 // Wenn wir die Message nicht ausgewertet haben, schauen wir
5975 // noch einmal nach, ob dort ein geplugtes Fenster steht,
5976 // welches wir dann benachrichtigen
5977 if ( rDef )
5978 rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
5979 bInWheelMsg--;
5981 break;
5983 case WM_COMMAND:
5984 ImplSalYieldMutexAcquireWithWait();
5985 rDef = !ImplHandleCommand( hWnd, wParam, lParam );
5986 ImplSalYieldMutexRelease();
5987 break;
5989 case WM_INITMENUPOPUP:
5990 ImplSalYieldMutexAcquireWithWait();
5991 rDef = !ImplHandleMenuActivate( hWnd, wParam, lParam );
5992 ImplSalYieldMutexRelease();
5993 break;
5995 case WM_MENUSELECT:
5996 ImplSalYieldMutexAcquireWithWait();
5997 rDef = !ImplHandleMenuSelect( hWnd, wParam, lParam );
5998 ImplSalYieldMutexRelease();
5999 break;
6001 case WM_SYSCOMMAND:
6002 ImplSalYieldMutexAcquireWithWait();
6003 nRet = ImplHandleSysCommand( hWnd, wParam, lParam );
6004 ImplSalYieldMutexRelease();
6005 if ( nRet )
6006 rDef = FALSE;
6007 break;
6009 case WM_MENUCHAR:
6010 nRet = ImplMenuChar( hWnd, wParam, lParam );
6011 if( nRet )
6012 rDef = FALSE;
6013 break;
6015 case WM_MEASUREITEM:
6016 nRet = ImplMeasureItem(hWnd, wParam, lParam);
6017 if( nRet )
6018 rDef = FALSE;
6019 break;
6021 case WM_DRAWITEM:
6022 nRet = ImplDrawItem(hWnd, wParam, lParam);
6023 if( nRet )
6024 rDef = FALSE;
6025 break;
6027 case WM_MOVE:
6028 case SAL_MSG_POSTMOVE:
6029 ImplHandleMoveMsg( hWnd );
6030 rDef = FALSE;
6031 break;
6032 case WM_SIZE:
6033 ImplHandleSizeMsg( hWnd, wParam, lParam );
6034 rDef = FALSE;
6035 break;
6036 case SAL_MSG_POSTCALLSIZE:
6037 ImplCallSizeHdl( hWnd );
6038 rDef = FALSE;
6039 break;
6041 case WM_GETMINMAXINFO:
6042 if ( ImplHandleMinMax( hWnd, lParam ) )
6043 rDef = FALSE;
6044 break;
6046 case WM_ERASEBKGND:
6047 nRet = 1;
6048 rDef = FALSE;
6049 break;
6050 case WM_PAINT:
6051 bCheckTimers = ImplHandlePaintMsg( hWnd );
6052 rDef = FALSE;
6053 break;
6054 case SAL_MSG_POSTPAINT:
6055 ImplHandlePaintMsg2( hWnd, (RECT*)wParam );
6056 bCheckTimers = true;
6057 rDef = FALSE;
6058 break;
6060 case SAL_MSG_FORCEPALETTE:
6061 ImplHandleForcePalette( hWnd );
6062 rDef = FALSE;
6063 break;
6065 case WM_QUERYNEWPALETTE:
6066 case SAL_MSG_POSTQUERYNEWPAL:
6067 nRet = ImplHandlePalette( TRUE, hWnd, nMsg, wParam, lParam, rDef );
6068 break;
6070 case WM_ACTIVATE:
6071 // Wenn wir aktiviert werden, dann wollen wir auch unsere
6072 // Palette setzen. Wir machen dieses in Activate,
6073 // damit andere externe Child-Fenster auch unsere Palette
6074 // ueberschreiben koennen. So wird unsere jedenfalls nur einmal
6075 // gesetzt und nicht immer rekursiv, da an allen anderen Stellen
6076 // diese nur als Background-Palette gesetzt wird
6077 if ( LOWORD( wParam ) != WA_INACTIVE )
6078 ImplSendMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
6079 break;
6081 case WM_ENABLE:
6082 // #95133# a system dialog is opened/closed, using our app window as parent
6084 WinSalFrame* pFrame = GetWindowPtr( hWnd );
6085 Window *pWin = NULL;
6086 if( pFrame )
6087 pWin = pFrame->GetWindow();
6089 if( !wParam )
6091 ImplSVData* pSVData = ImplGetSVData();
6092 pSVData->maAppData.mnModalMode++;
6094 // #106431#, hide SplashScreen
6095 if( pSVData->mpIntroWindow )
6096 pSVData->mpIntroWindow->Hide();
6098 if( pWin )
6100 pWin->EnableInput( FALSE, TRUE, TRUE, NULL );
6101 pWin->ImplIncModalCount(); // #106303# support frame based modal count
6104 else
6106 ImplGetSVData()->maAppData.mnModalMode--;
6107 if( pWin )
6109 pWin->EnableInput( TRUE, TRUE, TRUE, NULL );
6110 pWin->ImplDecModalCount(); // #106303# support frame based modal count
6114 break;
6116 case WM_KILLFOCUS:
6117 DestroyCaret();
6118 case WM_SETFOCUS:
6119 case SAL_MSG_POSTFOCUS:
6120 ImplHandleFocusMsg( hWnd );
6121 rDef = FALSE;
6122 break;
6124 case WM_CLOSE:
6125 ImplHandleCloseMsg( hWnd );
6126 rDef = FALSE;
6127 break;
6129 case WM_QUERYENDSESSION:
6130 if( !bInQueryEnd )
6132 // handle queryendsession only once
6133 bInQueryEnd = TRUE;
6134 nRet = !ImplHandleShutDownMsg( hWnd );
6135 rDef = FALSE;
6137 // Issue #16314#: ImplHandleShutDownMsg causes a PostMessage in case of allowing shutdown.
6138 // This posted message was never processed and cause Windows XP to hang after log off
6139 // if there are multiple sessions and the current session wasn't the first one started.
6140 // So if shutdown is allowed we assume that a post message was done and retrieve all
6141 // messages in the message queue and dispatch them before we return control to the system.
6143 if ( nRet )
6145 MSG msg;
6147 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
6149 DispatchMessage( &msg );
6153 else
6155 ImplSalYieldMutexAcquireWithWait();
6156 ImplSalYieldMutexRelease();
6157 rDef = TRUE;
6159 break;
6161 case WM_ENDSESSION:
6162 if( !wParam )
6163 bInQueryEnd = FALSE; // no shutdown: allow query again
6164 nRet = FALSE;
6165 rDef = FALSE;
6166 break;
6168 case WM_DISPLAYCHANGE:
6169 case WM_SETTINGCHANGE:
6170 case WM_DEVMODECHANGE:
6171 case WM_FONTCHANGE:
6172 case WM_SYSCOLORCHANGE:
6173 case WM_TIMECHANGE:
6174 ImplHandleSettingsChangeMsg( hWnd, nMsg, wParam, lParam );
6175 break;
6177 case WM_THEMECHANGED:
6178 GetSalData()->mbThemeChanged = TRUE;
6179 break;
6181 case SAL_MSG_USEREVENT:
6182 ImplHandleUserEvent( hWnd, lParam );
6183 rDef = FALSE;
6184 break;
6186 case SAL_MSG_CAPTUREMOUSE:
6187 SetCapture( hWnd );
6188 rDef = FALSE;
6189 break;
6190 case SAL_MSG_RELEASEMOUSE:
6191 if ( ::GetCapture() == hWnd )
6192 ReleaseCapture();
6193 rDef = FALSE;
6194 break;
6195 case SAL_MSG_TOTOP:
6196 ImplSalToTop( hWnd, (USHORT)wParam );
6197 rDef = FALSE;
6198 break;
6199 case SAL_MSG_SHOW:
6200 ImplSalShow( hWnd, (BOOL)wParam, (BOOL)lParam );
6201 rDef = FALSE;
6202 break;
6203 case SAL_MSG_SETINPUTCONTEXT:
6204 ImplSalFrameSetInputContext( hWnd, (const SalInputContext*)(void*)lParam );
6205 rDef = FALSE;
6206 break;
6207 case SAL_MSG_ENDEXTTEXTINPUT:
6208 ImplSalFrameEndExtTextInput( hWnd, (USHORT)(ULONG)(void*)wParam );
6209 rDef = FALSE;
6210 break;
6212 case WM_INPUTLANGCHANGE:
6213 ImplHandleInputLangChange( hWnd, wParam, lParam );
6214 break;
6216 case WM_IME_CHAR:
6217 // #103487#, some IMEs (eg, those that do not work onspot)
6218 // may send WM_IME_CHAR instead of WM_IME_COMPOSITION
6219 // we just handle it like a WM_CHAR message - seems to work fine
6220 ImplSalYieldMutexAcquireWithWait();
6221 rDef = !ImplHandleKeyMsg( hWnd, WM_CHAR, wParam, lParam, nRet );
6222 ImplSalYieldMutexRelease();
6223 break;
6225 case WM_IME_STARTCOMPOSITION:
6226 rDef = ImplHandleIMEStartComposition( hWnd );
6227 break;
6229 case WM_IME_COMPOSITION:
6230 rDef = ImplHandleIMEComposition( hWnd, lParam );
6231 break;
6233 case WM_IME_ENDCOMPOSITION:
6234 rDef = ImplHandleIMEEndComposition( hWnd );
6235 break;
6237 case WM_IME_NOTIFY:
6238 ImplHandleIMENotify( hWnd, wParam );
6239 break;
6240 case WM_APPCOMMAND:
6241 if( ImplHandleAppCommand( hWnd, lParam ) )
6243 rDef = false;
6244 nRet = 1;
6246 break;
6247 #if WINVER >= 0x0500
6248 case WM_IME_REQUEST:
6249 if ( PtrToInt( wParam ) == IMR_RECONVERTSTRING )
6251 nRet = ImplHandleIMEReconvertString( hWnd, lParam );
6252 rDef = FALSE;
6254 else if( PtrToInt( wParam ) == IMR_CONFIRMRECONVERTSTRING )
6256 nRet = ImplHandleIMEConfirmReconvertString( hWnd, lParam );
6257 rDef = FALSE;
6259 break;
6260 #endif // WINVER >= 0x0500
6263 // WheelMouse-Message abfangen
6264 if ( rDef && (nMsg == aSalShlData.mnWheelMsgId) && aSalShlData.mnWheelMsgId )
6266 // Gegen Rekursion absichern, falls wir vom IE oder dem externen
6267 // Fenster die Message wieder zurueckbekommen
6268 if ( !bInWheelMsg )
6270 bInWheelMsg++;
6271 // Zuerst wollen wir die Message dispatchen und dann darf auch
6272 // das SystemWindow drankommen
6273 WORD nKeyState = 0;
6274 if ( GetKeyState( VK_SHIFT ) & 0x8000 )
6275 nKeyState |= MK_SHIFT;
6276 if ( GetKeyState( VK_CONTROL ) & 0x8000 )
6277 nKeyState |= MK_CONTROL;
6278 // Mutex handling is inside from this call
6279 rDef = !ImplHandleWheelMsg( hWnd,
6280 WM_MOUSEWHEEL,
6281 MAKEWPARAM( nKeyState, (WORD)wParam ),
6282 lParam );
6283 if ( rDef )
6285 HWND hWheelWnd = ::GetFocus();
6286 if ( hWheelWnd && (hWheelWnd != hWnd) )
6288 nRet = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
6289 rDef = FALSE;
6291 else
6292 rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
6294 bInWheelMsg--;
6298 if( bCheckTimers )
6300 SalData* pSalData = GetSalData();
6301 if( pSalData->mnNextTimerTime )
6303 DWORD nCurTime = GetTickCount();
6304 if( pSalData->mnNextTimerTime < nCurTime )
6306 MSG aMsg;
6307 if( ! ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE | PM_NOYIELD ) )
6308 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_POSTTIMER, 0, nCurTime );
6313 return nRet;
6316 LRESULT CALLBACK SalFrameWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
6318 int bDef = TRUE;
6319 LRESULT nRet = 0;
6320 #ifdef __MINGW32__
6321 jmp_buf jmpbuf;
6322 __SEHandler han;
6323 if (__builtin_setjmp(jmpbuf) == 0)
6325 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
6326 #else
6327 __try
6329 #endif
6330 nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
6332 #ifdef __MINGW32__
6333 han.Reset();
6334 #else
6335 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
6338 #endif
6339 if ( bDef )
6340 nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
6341 return nRet;
6344 LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
6346 int bDef = TRUE;
6347 LRESULT nRet = 0;
6348 #ifdef __MINGW32__
6349 jmp_buf jmpbuf;
6350 __SEHandler han;
6351 if (__builtin_setjmp(jmpbuf) == 0)
6353 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
6354 #else
6355 __try
6357 #endif
6358 nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
6360 #ifdef __MINGW32__
6361 han.Reset();
6362 #else
6363 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
6366 #endif
6368 if ( bDef )
6369 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
6370 return nRet;
6373 // -----------------------------------------------------------------------
6375 BOOL ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult )
6377 // handle all messages concerning all frames so they get processed only once
6378 // Must work for Unicode and none Unicode
6379 BOOL bResult = FALSE;
6380 if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
6382 int bDef = TRUE;
6383 rlResult = ImplHandlePalette( FALSE, hWnd, nMsg, wParam, lParam, bDef );
6384 bResult = (bDef != 0);
6386 else if( nMsg == WM_DISPLAYCHANGE )
6388 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
6389 if( pSys )
6390 pSys->clearMonitors();
6391 bResult = (pSys != NULL);
6393 return bResult;
6396 // -----------------------------------------------------------------------
6398 BOOL ImplWriteLastError( DWORD lastError, const char *szApiCall )
6400 static int first=1;
6401 // if VCL_LOGFILE_ENABLED is set, Win32 API error messages can be written
6402 // to %TMP%/vcl.log or %TEMP%/vcl.log
6403 static char *logEnabled = getenv("VCL_LOGFILE_ENABLED");
6404 if( logEnabled )
6406 BOOL bSuccess = FALSE;
6407 static char *szTmp = getenv("TMP");
6408 if( !szTmp || !*szTmp )
6409 szTmp = getenv("TEMP");
6410 if( szTmp && *szTmp )
6412 char fname[5000];
6413 strcpy( fname, szTmp );
6414 if( fname[strlen(fname) - 1] != '\\' )
6415 strcat( fname, "\\");
6416 strcat( fname, "vcl.log" );
6417 FILE *fp = fopen( fname, "a" ); // always append
6418 if( fp )
6420 if( first )
6422 first = 0;
6423 fprintf( fp, "Process ID: %d (0x%x)\n", GetCurrentProcessId(), GetCurrentProcessId() );
6425 time_t aclock;
6426 time( &aclock ); // Get time in seconds
6427 struct tm *newtime = localtime( &aclock ); // Convert time to struct tm form
6428 fprintf( fp, asctime( newtime ) ); // print time stamp
6430 fprintf( fp, "%s returned %u (0x%x)\n", szApiCall, lastError, lastError );
6431 bSuccess = TRUE; // may be FormatMessage fails but we wrote at least the error code
6433 LPVOID lpMsgBuf;
6434 if (FormatMessageA(
6435 FORMAT_MESSAGE_ALLOCATE_BUFFER |
6436 FORMAT_MESSAGE_FROM_SYSTEM |
6437 FORMAT_MESSAGE_IGNORE_INSERTS,
6438 NULL,
6439 lastError,
6440 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
6441 (LPSTR) &lpMsgBuf,
6443 NULL ))
6445 fprintf( fp, " %s\n", (LPSTR)lpMsgBuf );
6446 LocalFree( lpMsgBuf );
6449 fclose( fp );
6452 return bSuccess;
6454 else
6455 return TRUE;
6458 // -----------------------------------------------------------------------