xref: /trunk/main/vcl/win/source/window/salframe.cxx (revision 5f27b83c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 // i72022: ad-hoc to forcibly enable reconversion
28 #if WINVER < 0x0500
29 #undef WINVER
30 #define WINVER 0x0500
31 #endif
32 
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/awt/Rectangle.hpp>
37 #include <comphelper/processfactory.hxx>
38 #include <unotools/misccfg.hxx>
39 
40 #include <string.h>
41 #include <limits.h>
42 
43 #include <stdio.h>
44 
45 #include <tools/svwin.h>
46 #ifdef __MINGW32__
47 #include <excpt.h>
48 #endif
49 
50 #include <rtl/string.h>
51 #include <rtl/ustring.h>
52 
53 #include <osl/module.h>
54 
55 #include <tools/debug.hxx>
56 
57 #include <vcl/sysdata.hxx>
58 #include <vcl/timer.hxx>
59 #include <vcl/settings.hxx>
60 #include <vcl/keycodes.hxx>
61 #include <vcl/window.hxx>
62 #include <vcl/wrkwin.hxx>
63 #include <vcl/svapp.hxx>
64 #include <vcl/impdel.hxx>
65 
66 // Warning in SDK header
67 #if defined(_MSC_VER) && (_MSC_VER > 1400)
68 #pragma warning( disable: 4242 4244 )
69 #endif
70 #include <win/wincomp.hxx>
71 #include <win/salids.hrc>
72 #include <win/saldata.hxx>
73 #include <win/salinst.h>
74 #include <win/salbmp.h>
75 #include <win/salgdi.h>
76 #include <win/salsys.h>
77 #include <win/salframe.h>
78 #include <win/salvd.h>
79 #include <win/salmenu.h>
80 #include <win/salobj.h>
81 #include <win/saltimer.h>
82 
83 #include <impbmp.hxx>
84 #include <window.h>
85 #include <sallayout.hxx>
86 
87 #define COMPILE_MULTIMON_STUBS
88 #include <multimon.h>
89 #include <vector>
90 #ifdef __MINGW32__
91 #include <algorithm>
92 using ::std::max;
93 #endif
94 
95 #include <com/sun/star/uno/Exception.hdl>
96 
97 #include <time.h>
98 
99 using ::rtl::OUString;
100 using namespace ::com::sun::star;
101 using namespace ::com::sun::star::uno;
102 using namespace ::com::sun::star::lang;
103 using namespace ::com::sun::star::container;
104 using namespace ::com::sun::star::beans;
105 
106 // The following defines are newly added in Longhorn
107 #ifndef WM_MOUSEHWHEEL
108 # define WM_MOUSEHWHEEL            0x020E
109 #endif
110 #ifndef SPI_GETWHEELSCROLLCHARS
111 # define SPI_GETWHEELSCROLLCHARS   0x006C
112 #endif
113 #ifndef SPI_SETWHEELSCROLLCHARS
114 # define SPI_SETWHEELSCROLLCHARS   0x006D
115 #endif
116 
117 
118 
119 #if OSL_DEBUG_LEVEL > 1
120 void MyOutputDebugString( char *s) { OutputDebugString( s ); }
121 #endif
122 
123 // misssing prototypes and constants for LayeredWindows
124 extern "C" {
125     //WINUSERAPI sal_Bool WINAPI SetLayeredWindowAttributes(HWND,COLORREF,BYTE,DWORD);
126     typedef sal_Bool ( WINAPI * SetLayeredWindowAttributes_Proc_T ) (HWND,COLORREF,BYTE,DWORD);
127     static SetLayeredWindowAttributes_Proc_T lpfnSetLayeredWindowAttributes;
128 };
129 
130 // =======================================================================
131 
132 const unsigned int WM_USER_SYSTEM_WINDOW_ACTIVATED = RegisterWindowMessageA("SYSTEM_WINDOW_ACTIVATED");
133 
134 sal_Bool WinSalFrame::mbInReparent = FALSE;
135 
136 // =======================================================================
137 
138 // Wegen Fehler in Windows-Headerfiles
139 #ifndef IMN_OPENCANDIDATE
140 #define IMN_OPENCANDIDATE               0x0005
141 #endif
142 #ifndef IMN_CLOSECANDIDATE
143 #define IMN_CLOSECANDIDATE              0x0004
144 #endif
145 
146 #ifndef WM_THEMECHANGED
147 #define WM_THEMECHANGED                 0x031A
148 #endif
149 
150 // Macros for support of WM_UNICHAR & Keyman 6.0
151 #define Uni_UTF32ToSurrogate1(ch)   (((unsigned long) (ch) - 0x10000) / 0x400 + 0xD800)
152 #define Uni_UTF32ToSurrogate2(ch)   (((unsigned long) (ch) - 0x10000) % 0x400 + 0xDC00)
153 #define Uni_SupplementaryPlanesStart    0x10000
154 
155 // =======================================================================
156 
157 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame );
158 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect = NULL );
159 
160 static void ImplSaveFrameState( WinSalFrame* pFrame )
161 {
162     // Position, Groesse und Status fuer GetWindowState() merken
163     if ( !pFrame->mbFullScreen )
164     {
165         sal_Bool bVisible = (GetWindowStyle( pFrame->mhWnd ) & WS_VISIBLE) != 0;
166         if ( IsIconic( pFrame->mhWnd ) )
167         {
168             pFrame->maState.mnState |= SAL_FRAMESTATE_MINIMIZED;
169             if ( bVisible )
170                 pFrame->mnShowState = SW_SHOWMAXIMIZED;
171         }
172         else if ( IsZoomed( pFrame->mhWnd ) )
173         {
174             pFrame->maState.mnState &= ~SAL_FRAMESTATE_MINIMIZED;
175             pFrame->maState.mnState |= SAL_FRAMESTATE_MAXIMIZED;
176             if ( bVisible )
177                 pFrame->mnShowState = SW_SHOWMAXIMIZED;
178             pFrame->mbRestoreMaximize = TRUE;
179 
180             WINDOWPLACEMENT aPlacement;
181             aPlacement.length = sizeof(aPlacement);
182             if( GetWindowPlacement( pFrame->mhWnd, &aPlacement ) )
183             {
184                 RECT aRect = aPlacement.rcNormalPosition;
185                 RECT aRect2 = aRect;
186                 AdjustWindowRectEx( &aRect2, GetWindowStyle( pFrame->mhWnd ),
187                                     FALSE,  GetWindowExStyle( pFrame->mhWnd ) );
188                 long nTopDeco = abs( aRect.top - aRect2.top );
189                 long nLeftDeco = abs( aRect.left - aRect2.left );
190                 long nBottomDeco = abs( aRect.bottom - aRect2.bottom );
191                 long nRightDeco = abs( aRect.right - aRect2.right );
192 
193                 pFrame->maState.mnX      = aRect.left + nLeftDeco;
194                 pFrame->maState.mnY      = aRect.top + nTopDeco;
195                 pFrame->maState.mnWidth  = aRect.right - aRect.left - nLeftDeco - nRightDeco;
196                 pFrame->maState.mnHeight = aRect.bottom - aRect.top - nTopDeco - nBottomDeco;
197             }
198         }
199         else
200         {
201             RECT aRect;
202             GetWindowRect( pFrame->mhWnd, &aRect );
203 
204             // to be consistent with Unix, the frame state is without(!) decoration
205             RECT aRect2 = aRect;
206 		    AdjustWindowRectEx( &aRect2, GetWindowStyle( pFrame->mhWnd ),
207 							FALSE,     GetWindowExStyle( pFrame->mhWnd ) );
208             long nTopDeco = abs( aRect.top - aRect2.top );
209             long nLeftDeco = abs( aRect.left - aRect2.left );
210             long nBottomDeco = abs( aRect.bottom - aRect2.bottom );
211             long nRightDeco = abs( aRect.right - aRect2.right );
212 
213             pFrame->maState.mnState &= ~(SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED);
214             // subtract decoration
215             pFrame->maState.mnX      = aRect.left+nLeftDeco;
216             pFrame->maState.mnY      = aRect.top+nTopDeco;
217             pFrame->maState.mnWidth  = aRect.right-aRect.left-nLeftDeco-nRightDeco;
218             pFrame->maState.mnHeight = aRect.bottom-aRect.top-nTopDeco-nBottomDeco;
219             if ( bVisible )
220                 pFrame->mnShowState = SW_SHOWNORMAL;
221             pFrame->mbRestoreMaximize = FALSE;
222         }
223     }
224 }
225 
226 // -----------------------------------------------------------------------
227 
228 // if pParentRect is set, the workarea of the monitor that contains pParentRect is returned
229 void ImplSalGetWorkArea( HWND hWnd, RECT *pRect, const RECT *pParentRect )
230 {
231 	static int winVerChecked = 0;
232 	static int winVerOk = 0;
233 
234     // check if we or our parent is fullscreen, then the taskbar should be ignored
235     bool bIgnoreTaskbar = false;
236     WinSalFrame* pFrame = GetWindowPtr( hWnd );
237 	if( pFrame )
238     {
239 	    Window *pWin = pFrame->GetWindow();
240         while( pWin )
241         {
242             WorkWindow *pWorkWin = (pWin->GetType() == WINDOW_WORKWINDOW) ? (WorkWindow *) pWin : NULL;
243             if( pWorkWin && pWorkWin->ImplGetWindowImpl()->mbReallyVisible && pWorkWin->IsFullScreenMode() )
244             {
245                 bIgnoreTaskbar = true;
246                 break;
247             }
248             else
249                 pWin = pWin->ImplGetWindowImpl()->mpParent;
250         }
251     }
252 
253     if( !winVerChecked )
254 	{
255 		winVerChecked = 1;
256 		winVerOk = 1;
257 
258 		// multi monitor calls not available on Win95/NT
259         if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
260         {
261             if ( aSalShlData.maVersionInfo.dwMajorVersion <= 4 )
262                 winVerOk = 0;	// NT
263         }
264         else if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
265         {
266             if ( aSalShlData.maVersionInfo.dwMajorVersion == 4 && aSalShlData.maVersionInfo.dwMinorVersion == 0 )
267                 winVerOk = 0;	// Win95
268         }
269 	}
270 
271     // calculates the work area taking multiple monitors into account
272     if( winVerOk )
273     {
274         static int nMonitors = GetSystemMetrics( SM_CMONITORS );
275         if( nMonitors == 1 )
276         {
277             if( bIgnoreTaskbar )
278             {
279                 pRect->left = pRect->top = 0;
280                 pRect->right   = GetSystemMetrics( SM_CXSCREEN );
281                 pRect->bottom  = GetSystemMetrics( SM_CYSCREEN );
282             }
283             else
284 	            SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 );
285         }
286         else
287         {
288             if( pParentRect != NULL )
289             {
290                 // return the size of the monitor where pParentRect lives
291                 HMONITOR hMonitor;
292                 MONITORINFO mi;
293 
294                 // get the nearest monitor to the passed rect.
295                 hMonitor = MonitorFromRect(pParentRect, MONITOR_DEFAULTTONEAREST);
296 
297                 // get the work area or entire monitor rect.
298                 mi.cbSize = sizeof(mi);
299                 GetMonitorInfo(hMonitor, &mi);
300                 if( !bIgnoreTaskbar )
301                     *pRect = mi.rcWork;
302                 else
303                     *pRect = mi.rcMonitor;
304             }
305             else
306             {
307                 // return the union of all monitors
308                 pRect->left = GetSystemMetrics( SM_XVIRTUALSCREEN );
309                 pRect->top = GetSystemMetrics( SM_YVIRTUALSCREEN );
310                 pRect->right = pRect->left + GetSystemMetrics( SM_CXVIRTUALSCREEN );
311                 pRect->bottom = pRect->top + GetSystemMetrics( SM_CYVIRTUALSCREEN );
312 
313                 // virtualscreen does not take taskbar into account, so use the corresponding
314                 // diffs between screen and workarea from the default screen
315                 // however, this is still not perfect: the taskbar might not be on the primary screen
316                 if( !bIgnoreTaskbar )
317                 {
318                     RECT wRect, scrRect;
319                     SystemParametersInfo( SPI_GETWORKAREA, 0, &wRect, 0 );
320                     scrRect.left = 0;
321                     scrRect.top = 0;
322                     scrRect.right = GetSystemMetrics( SM_CXSCREEN );
323                     scrRect.bottom = GetSystemMetrics( SM_CYSCREEN );
324 
325                     pRect->left += wRect.left;
326                     pRect->top += wRect.top;
327                     pRect->right -= scrRect.right - wRect.right;
328                     pRect->bottom -= scrRect.bottom - wRect.bottom;
329                 }
330             }
331         }
332     }
333     else
334     {
335         if( bIgnoreTaskbar )
336         {
337             pRect->left = pRect->top = 0;
338             pRect->right   = GetSystemMetrics( SM_CXSCREEN );
339             pRect->bottom  = GetSystemMetrics( SM_CYSCREEN );
340         }
341         else
342 	        SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 );
343     }
344 }
345 
346 // =======================================================================
347 
348 SalFrame* ImplSalCreateFrame( WinSalInstance* pInst,
349                               HWND hWndParent, sal_uLong nSalFrameStyle )
350 {
351     WinSalFrame*   pFrame = new WinSalFrame;
352     HWND        hWnd;
353     DWORD       nSysStyle = 0;
354     DWORD       nExSysStyle = 0;
355     sal_Bool        bSubFrame = FALSE;
356 
357     if( getenv( "SAL_SYNCHRONIZE" ) )   // no buffering of drawing commands
358         GdiSetBatchLimit( 1 );
359 
360     static int bLayeredAPI = -1;
361     if( bLayeredAPI == -1 )
362     {
363         bLayeredAPI = 0;
364         // check for W2k and XP
365         if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
366         {
367             oslModule pLib = osl_loadAsciiModule( "user32", SAL_LOADMODULE_DEFAULT );
368             oslGenericFunction pFunc = NULL;
369             if( pLib )
370                 pFunc = osl_getAsciiFunctionSymbol( pLib, "SetLayeredWindowAttributes" );
371 
372             lpfnSetLayeredWindowAttributes = ( SetLayeredWindowAttributes_Proc_T ) pFunc;
373 
374             bLayeredAPI = pFunc ? 1 : 0;
375         }
376     }
377     static const char* pEnvTransparentFloats = getenv("SAL_TRANSPARENT_FLOATS" );
378 
379     // determine creation data
380     if ( nSalFrameStyle & (SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_SYSTEMCHILD) )
381     {
382         nSysStyle |= WS_CHILD;
383         if( nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD )
384             nSysStyle |= WS_CLIPSIBLINGS;
385     }
386     else
387     {
388         // #i87402# commenting out WS_CLIPCHILDREN
389         // this breaks SAL_FRAME_STYLE_SYSTEMCHILD handling, which is not
390         // used currently. Probably SAL_FRAME_STYLE_SYSTEMCHILD should be
391         // removed again.
392 
393         // nSysStyle  |= WS_CLIPCHILDREN;
394         if ( hWndParent )
395         {
396             nSysStyle |= WS_POPUP;
397             bSubFrame = TRUE;
398             pFrame->mbNoIcon = TRUE;
399         }
400         else
401         {
402             // Only with WS_OVRLAPPED we get a useful default position/size
403             if ( (nSalFrameStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE)) ==
404                  (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE) )
405                 nSysStyle |= WS_OVERLAPPED;
406             else
407             {
408                 nSysStyle |= WS_POPUP;
409                 if ( !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) )
410                     nExSysStyle |= WS_EX_TOOLWINDOW;    // avoid taskbar appearance, for eg splash screen
411             }
412         }
413 
414         if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
415         {
416             pFrame->mbCaption = TRUE;
417             nSysStyle |= WS_SYSMENU | WS_CAPTION;
418             if ( !hWndParent )
419                 nSysStyle |= WS_SYSMENU | WS_MINIMIZEBOX;
420             else
421                 nExSysStyle |= WS_EX_DLGMODALFRAME;
422 
423             if ( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE )
424             {
425                 pFrame->mbSizeBorder = TRUE;
426                 nSysStyle |= WS_THICKFRAME;
427                 if ( !hWndParent )
428                     nSysStyle |= WS_MAXIMIZEBOX;
429             }
430             else
431                 pFrame->mbFixBorder = TRUE;
432 
433             if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT )
434                 nExSysStyle |= WS_EX_APPWINDOW;
435         }
436         if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW
437             // #100656# toolwindows lead to bad alt-tab behaviour, if they have the focus
438             // you must press it twice to leave the application
439             // so toolwindows are only used for non sizeable windows
440             // which are typically small, so a small caption makes sense
441 
442             // #103578# looked too bad - above changes reverted
443             /* && !(nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE) */ )
444         {
445             pFrame->mbNoIcon = TRUE;
446             nExSysStyle |= WS_EX_TOOLWINDOW;
447             if ( pEnvTransparentFloats && bLayeredAPI == 1 /*&& !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) */)
448                 nExSysStyle |= WS_EX_LAYERED;
449         }
450     }
451     if ( nSalFrameStyle & SAL_FRAME_STYLE_FLOAT )
452     {
453         nExSysStyle |= WS_EX_TOOLWINDOW;
454         pFrame->mbFloatWin = TRUE;
455 
456         if ( (bLayeredAPI == 1) && (pEnvTransparentFloats /* does not work remote! || (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) */ )  )
457             nExSysStyle |= WS_EX_LAYERED;
458 
459     }
460     if( (nSalFrameStyle & SAL_FRAME_STYLE_TOOLTIP) || (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
461         nExSysStyle |= WS_EX_TOPMOST;
462 
463     // init frame data
464     pFrame->mnStyle = nSalFrameStyle;
465 
466     // determine show style
467     pFrame->mnShowState = SW_SHOWNORMAL;
468     if ( (nSysStyle & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME) )
469     {
470         if ( GetSystemMetrics( SM_CXSCREEN ) <= 1024 )
471             pFrame->mnShowState = SW_SHOWMAXIMIZED;
472         else
473         {
474             if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT )
475             {
476                 SalData* pSalData = GetSalData();
477                 pFrame->mnShowState = pSalData->mnCmdShow;
478                 if ( (pFrame->mnShowState != SW_SHOWMINIMIZED) &&
479                      (pFrame->mnShowState != SW_MINIMIZE) &&
480                      (pFrame->mnShowState != SW_SHOWMINNOACTIVE) )
481                 {
482                     if ( (pFrame->mnShowState == SW_SHOWMAXIMIZED) ||
483                          (pFrame->mnShowState == SW_MAXIMIZE) )
484                         pFrame->mbOverwriteState = FALSE;
485                     pFrame->mnShowState = SW_SHOWMAXIMIZED;
486                 }
487                 else
488                     pFrame->mbOverwriteState = FALSE;
489             }
490             else
491             {
492                 // Document Windows are also maximized, if the current Document Window
493                 // is also maximized
494                 HWND hWnd = GetForegroundWindow();
495                 if ( hWnd && IsMaximized( hWnd ) &&
496                      (GetWindowInstance( hWnd ) == pInst->mhInst) &&
497                      ((GetWindowStyle( hWnd ) & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME)) )
498                     pFrame->mnShowState = SW_SHOWMAXIMIZED;
499             }
500         }
501     }
502 
503     // create frame
504     if( true/*aSalShlData.mbWNT*/ )
505     {
506         LPCWSTR pClassName;
507         if ( bSubFrame )
508         {
509             if ( nSalFrameStyle & (SAL_FRAME_STYLE_MOVEABLE|SAL_FRAME_STYLE_NOSHADOW) ) // check if shadow not wanted
510                 pClassName = SAL_SUBFRAME_CLASSNAMEW;
511             else
512                 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW;    // undecorated floaters will get shadow on XP
513         }
514         else
515         {
516             if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
517                 pClassName = SAL_FRAME_CLASSNAMEW;
518             else
519                 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW;
520         }
521         hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
522                                 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
523                                 hWndParent, 0, pInst->mhInst, (void*)pFrame );
524         if( !hWnd )
525             ImplWriteLastError( GetLastError(), "CreateWindowEx" );
526 #if OSL_DEBUG_LEVEL > 1
527         // set transparency value
528         if( bLayeredAPI == 1 && GetWindowExStyle( hWnd ) & WS_EX_LAYERED )
529             lpfnSetLayeredWindowAttributes( hWnd, 0, 230, 0x00000002 /*LWA_ALPHA*/ );
530 #endif
531     }
532     if ( !hWnd )
533     {
534         delete pFrame;
535         return NULL;
536     }
537 
538     // If we have an Window with an Caption Bar and without
539     // an MaximizeBox, we change the SystemMenu
540     if ( (nSysStyle & (WS_CAPTION | WS_MAXIMIZEBOX)) == (WS_CAPTION) )
541     {
542         HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
543         if ( hSysMenu )
544         {
545             if ( !(nSysStyle & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX)) )
546                 DeleteMenu( hSysMenu, SC_RESTORE, MF_BYCOMMAND );
547             else
548                 EnableMenuItem( hSysMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
549             if ( !(nSysStyle & WS_MINIMIZEBOX) )
550                 DeleteMenu( hSysMenu, SC_MINIMIZE, MF_BYCOMMAND );
551             if ( !(nSysStyle & WS_MAXIMIZEBOX) )
552                 DeleteMenu( hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND );
553             if ( !(nSysStyle & WS_THICKFRAME) )
554                 DeleteMenu( hSysMenu, SC_SIZE, MF_BYCOMMAND );
555         }
556     }
557     if ( (nSysStyle & WS_SYSMENU) && !(nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE) )
558     {
559         HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
560         if ( hSysMenu )
561             EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
562     }
563 
564     // reset input context
565     pFrame->mhDefIMEContext = ImmAssociateContext( hWnd, 0 );
566 
567     // determine output size and state
568     RECT aRect;
569     GetClientRect( hWnd, &aRect );
570     pFrame->mnWidth  = aRect.right;
571     pFrame->mnHeight = aRect.bottom;
572     ImplSaveFrameState( pFrame );
573     pFrame->mbDefPos = TRUE;
574 
575 	UpdateFrameGeometry( hWnd, pFrame );
576 
577     if( pFrame->mnShowState == SW_SHOWMAXIMIZED )
578 	{
579 		// #96084 set a useful internal window size because
580 		// the window will not be maximized (and the size updated) before show()
581 
582         SetMaximizedFrameGeometry( hWnd, pFrame );
583 	}
584 
585     return pFrame;
586 }
587 
588 // helper that only creates the HWND
589 // to allow for easy reparenting of system windows, (i.e. destroy and create new)
590 HWND ImplSalReCreateHWND( HWND hWndParent, HWND oldhWnd, sal_Bool bAsChild )
591 {
592     HINSTANCE hInstance = GetSalData()->mhInst;
593     ULONG nSysStyle     = GetWindowLong( oldhWnd, GWL_STYLE );
594     ULONG nExSysStyle   = GetWindowLong( oldhWnd, GWL_EXSTYLE );
595 
596     if( bAsChild )
597     {
598         nSysStyle = WS_CHILD;
599         nExSysStyle = 0;
600     }
601 
602     LPCWSTR pClassName = SAL_SUBFRAME_CLASSNAMEW;
603     HWND hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
604                                 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
605                                 hWndParent, 0, hInstance, (void*)GetWindowPtr( oldhWnd ) );
606     return hWnd;
607 }
608 
609 // =======================================================================
610 
611 // Uebersetzungstabelle von System-Keycodes in StarView-Keycodes
612 #define KEY_TAB_SIZE     146
613 
614 static sal_uInt16 aImplTranslateKeyTab[KEY_TAB_SIZE] =
615 {
616     // StarView-Code      System-Code                         Index
617     0,                    //                                  0
618     0,                    // VK_LBUTTON                       1
619     0,                    // VK_RBUTTON                       2
620     0,                    // VK_CANCEL                        3
621     0,                    // VK_MBUTTON                       4
622     0,                    //                                  5
623     0,                    //                                  6
624     0,                    //                                  7
625     KEY_BACKSPACE,        // VK_BACK                          8
626     KEY_TAB,              // VK_TAB                           9
627     0,                    //                                  10
628     0,                    //                                  11
629     0,                    // VK_CLEAR                         12
630     KEY_RETURN,           // VK_RETURN                        13
631     0,                    //                                  14
632     0,                    //                                  15
633     0,                    // VK_SHIFT                         16
634     0,                    // VK_CONTROL                       17
635     0,                    // VK_MENU                          18
636     0,                    // VK_PAUSE                         19
637     0,                    // VK_CAPITAL                       20
638     0,                    // VK_HANGUL                        21
639     0,                    //                                  22
640     0,                    //                                  23
641     0,                    //                                  24
642     KEY_HANGUL_HANJA,     // VK_HANJA                         25
643     0,                    //                                  26
644     KEY_ESCAPE,           // VK_ESCAPE                        27
645     0,                    //                                  28
646     0,                    //                                  29
647     0,                    //                                  30
648     0,                    //                                  31
649     KEY_SPACE,            // VK_SPACE                         32
650     KEY_PAGEUP,           // VK_PRIOR                         33
651     KEY_PAGEDOWN,         // VK_NEXT                          34
652     KEY_END,              // VK_END                           35
653     KEY_HOME,             // VK_HOME                          36
654     KEY_LEFT,             // VK_LEFT                          37
655     KEY_UP,               // VK_UP                            38
656     KEY_RIGHT,            // VK_RIGHT                         39
657     KEY_DOWN,             // VK_DOWN                          40
658     0,                    // VK_SELECT                        41
659     0,                    // VK_PRINT                         42
660     0,                    // VK_EXECUTE                       43
661     0,                    // VK_SNAPSHOT                      44
662     KEY_INSERT,           // VK_INSERT                        45
663     KEY_DELETE,           // VK_DELETE                        46
664     KEY_HELP,             // VK_HELP                          47
665     KEY_0,                //                                  48
666     KEY_1,                //                                  49
667     KEY_2,                //                                  50
668     KEY_3,                //                                  51
669     KEY_4,                //                                  52
670     KEY_5,                //                                  53
671     KEY_6,                //                                  54
672     KEY_7,                //                                  55
673     KEY_8,                //                                  56
674     KEY_9,                //                                  57
675     0,                    //                                  58
676     0,                    //                                  59
677     0,                    //                                  60
678     0,                    //                                  61
679     0,                    //                                  62
680     0,                    //                                  63
681     0,                    //                                  64
682     KEY_A,                //                                  65
683     KEY_B,                //                                  66
684     KEY_C,                //                                  67
685     KEY_D,                //                                  68
686     KEY_E,                //                                  69
687     KEY_F,                //                                  70
688     KEY_G,                //                                  71
689     KEY_H,                //                                  72
690     KEY_I,                //                                  73
691     KEY_J,                //                                  74
692     KEY_K,                //                                  75
693     KEY_L,                //                                  76
694     KEY_M,                //                                  77
695     KEY_N,                //                                  78
696     KEY_O,                //                                  79
697     KEY_P,                //                                  80
698     KEY_Q,                //                                  81
699     KEY_R,                //                                  82
700     KEY_S,                //                                  83
701     KEY_T,                //                                  84
702     KEY_U,                //                                  85
703     KEY_V,                //                                  86
704     KEY_W,                //                                  87
705     KEY_X,                //                                  88
706     KEY_Y,                //                                  89
707     KEY_Z,                //                                  90
708     0,                    // VK_LWIN                          91
709     0,                    // VK_RWIN                          92
710     KEY_CONTEXTMENU,      // VK_APPS                          93
711     0,                    //                                  94
712     0,                    //                                  95
713     KEY_0,                // VK_NUMPAD0                       96
714     KEY_1,                // VK_NUMPAD1                       97
715     KEY_2,                // VK_NUMPAD2                       98
716     KEY_3,                // VK_NUMPAD3                       99
717     KEY_4,                // VK_NUMPAD4                      100
718     KEY_5,                // VK_NUMPAD5                      101
719     KEY_6,                // VK_NUMPAD6                      102
720     KEY_7,                // VK_NUMPAD7                      103
721     KEY_8,                // VK_NUMPAD8                      104
722     KEY_9,                // VK_NUMPAD9                      105
723     KEY_MULTIPLY,         // VK_MULTIPLY                     106
724     KEY_ADD,              // VK_ADD                          107
725     KEY_DECIMAL,          // VK_SEPARATOR                    108
726     KEY_SUBTRACT,         // VK_SUBTRACT                     109
727     KEY_DECIMAL,          // VK_DECIMAL                      110
728     KEY_DIVIDE,           // VK_DIVIDE                       111
729     KEY_F1,               // VK_F1                           112
730     KEY_F2,               // VK_F2                           113
731     KEY_F3,               // VK_F3                           114
732     KEY_F4,               // VK_F4                           115
733     KEY_F5,               // VK_F5                           116
734     KEY_F6,               // VK_F6                           117
735     KEY_F7,               // VK_F7                           118
736     KEY_F8,               // VK_F8                           119
737     KEY_F9,               // VK_F9                           120
738     KEY_F10,              // VK_F10                          121
739     KEY_F11,              // VK_F11                          122
740     KEY_F12,              // VK_F12                          123
741     KEY_F13,              // VK_F13                          124
742     KEY_F14,              // VK_F14                          125
743     KEY_F15,              // VK_F15                          126
744     KEY_F16,              // VK_F16                          127
745     KEY_F17,              // VK_F17                          128
746     KEY_F18,              // VK_F18                          129
747     KEY_F19,              // VK_F19                          130
748     KEY_F20,              // VK_F20                          131
749     KEY_F21,              // VK_F21                          132
750     KEY_F22,              // VK_F22                          133
751     KEY_F23,              // VK_F23                          134
752     KEY_F24,              // VK_F24                          135
753     0,                    //                                 136
754     0,                    //                                 137
755     0,                    //                                 138
756     0,                    //                                 139
757     0,                    //                                 140
758     0,                    //                                 141
759     0,                    //                                 142
760     0,                    //                                 143
761     0,                    // NUMLOCK                         144
762     0                     // SCROLLLOCK                      145
763 };
764 
765 // =======================================================================
766 
767 static UINT ImplSalGetWheelScrollLines()
768 {
769     UINT nScrLines = 0;
770     HWND hWndMsWheel = WIN_FindWindow( MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE );
771     if ( hWndMsWheel )
772     {
773         UINT nGetScrollLinesMsgId = RegisterWindowMessage( MSH_SCROLL_LINES );
774         nScrLines = (UINT)ImplSendMessage( hWndMsWheel, nGetScrollLinesMsgId, 0, 0 );
775     }
776 
777     if ( !nScrLines )
778         if( !SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &nScrLines, 0 ) )
779             nScrLines = 0 ;
780 
781     if ( !nScrLines )
782         nScrLines = 3;
783 
784     return nScrLines;
785 }
786 
787 // -----------------------------------------------------------------------
788 
789 static UINT ImplSalGetWheelScrollChars()
790 {
791     UINT nScrChars = 0;
792     if( !SystemParametersInfo( SPI_GETWHEELSCROLLCHARS, 0, &nScrChars, 0 ) )
793     {
794         // Depending on Windows version, use proper default or 1 (when
795         // driver emulates hscroll)
796         if( VER_PLATFORM_WIN32_NT == aSalShlData.maVersionInfo.dwPlatformId &&
797             aSalShlData.maVersionInfo.dwMajorVersion < 6 )
798         {
799             // Windows 2000 & WinXP : emulating driver, use step size
800             // of 1
801             return 1;
802         }
803         else
804         {
805             // Longhorn or above: use proper default value of 3
806             return 3;
807         }
808     }
809 
810     // system settings successfully read
811     return nScrChars;
812 }
813 
814 // -----------------------------------------------------------------------
815 
816 static void ImplSalAddBorder( const WinSalFrame* pFrame, int& width, int& height )
817 {
818     // transform client size into window size
819     RECT    aWinRect;
820     aWinRect.left   = 0;
821     aWinRect.right  = width-1;
822     aWinRect.top    = 0;
823     aWinRect.bottom = height-1;
824     AdjustWindowRectEx( &aWinRect, GetWindowStyle( pFrame->mhWnd ),
825                         FALSE,     GetWindowExStyle( pFrame->mhWnd ) );
826     width  = aWinRect.right - aWinRect.left + 1;
827     height = aWinRect.bottom - aWinRect.top + 1;
828 }
829 
830 // -----------------------------------------------------------------------
831 
832 static void ImplSalCalcFullScreenSize( const WinSalFrame* pFrame,
833                                        int& rX, int& rY, int& rDX, int& rDY )
834 {
835     // set window to screen size
836     int nFrameX;
837     int nFrameY;
838     int nCaptionY;
839 	int nScreenX = 0;
840 	int nScreenY = 0;
841     int nScreenDX = 0;
842     int nScreenDY = 0;
843 
844     if ( pFrame->mbSizeBorder )
845     {
846         nFrameX = GetSystemMetrics( SM_CXSIZEFRAME );
847         nFrameY = GetSystemMetrics( SM_CYSIZEFRAME );
848     }
849     else if ( pFrame->mbFixBorder )
850     {
851         nFrameX = GetSystemMetrics( SM_CXFIXEDFRAME );
852         nFrameY = GetSystemMetrics( SM_CYFIXEDFRAME );
853     }
854     else if ( pFrame->mbBorder )
855     {
856         nFrameX = GetSystemMetrics( SM_CXBORDER );
857         nFrameY = GetSystemMetrics( SM_CYBORDER );
858     }
859     else
860     {
861         nFrameX = 0;
862         nFrameY = 0;
863     }
864     if ( pFrame->mbCaption )
865         nCaptionY = GetSystemMetrics( SM_CYCAPTION );
866     else
867         nCaptionY = 0;
868 
869 	try
870 	{
871 	    uno::Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
872 	    uno::Reference< XIndexAccess > xMultiMon( xFactory->createInstance(OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DisplayAccess" ) ) ), UNO_QUERY_THROW );
873         sal_Int32 nMonitors = xMultiMon->getCount();
874 		if( (pFrame->mnDisplay >= 0) && (pFrame->mnDisplay < nMonitors) )
875 		{
876 		    uno::Reference< XPropertySet > xMonitor( xMultiMon->getByIndex( pFrame->mnDisplay ), UNO_QUERY_THROW );
877 			com::sun::star::awt::Rectangle aRect;
878 			if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect )
879 			{
880 				nScreenX = aRect.X;
881 				nScreenY = aRect.Y;
882 				nScreenDX = aRect.Width+1;  // difference between java/awt convention and vcl
883 				nScreenDY = aRect.Height+1; // difference between java/awt convention and vcl
884 			}
885 		}
886 		else
887 		{
888             Rectangle aCombined;
889             uno::Reference< XPropertySet > xMonitor( xMultiMon->getByIndex( 0 ), UNO_QUERY_THROW );
890 			com::sun::star::awt::Rectangle aRect;
891 			if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect )
892 			{
893                 aCombined.Left()   = aRect.X;
894                 aCombined.Top()    = aRect.Y;
895                 aCombined.Right()  = aRect.X + aRect.Width;
896                 aCombined.Bottom() = aRect.Y + aRect.Height;
897                 for( sal_Int32 i = 1 ; i < nMonitors ; i++ )
898                 {
899                     xMonitor = uno::Reference< XPropertySet >( xMultiMon->getByIndex(i), UNO_QUERY_THROW );
900                     if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect )
901                     {
902                         aCombined.Union( Rectangle( aRect.X, aRect.Y, aRect.X+aRect.Width, aRect.Y+aRect.Height ) );
903                     }
904                 }
905             }
906             nScreenX  = aCombined.Left();
907             nScreenY  = aCombined.Top();
908             nScreenDX = aCombined.GetWidth();
909             nScreenDY = aCombined.GetHeight();
910 		}
911 	}
912 	catch( Exception& )
913 	{
914 	}
915 
916 	if( !nScreenDX || !nScreenDY )
917 	{
918 	    nScreenDX   = GetSystemMetrics( SM_CXSCREEN );
919 		nScreenDY   = GetSystemMetrics( SM_CYSCREEN );
920 	}
921 
922     rX  = nScreenX -nFrameX;
923     rY  = nScreenY -(nFrameY+nCaptionY);
924     rDX = nScreenDX+(nFrameX*2);
925     rDY = nScreenDY+(nFrameY*2)+nCaptionY;
926 }
927 
928 // -----------------------------------------------------------------------
929 
930 static void ImplSalFrameFullScreenPos( WinSalFrame* pFrame, sal_Bool bAlways = FALSE )
931 {
932     if ( bAlways || !IsIconic( pFrame->mhWnd ) )
933     {
934         // set window to screen size
935         int nX;
936         int nY;
937         int nWidth;
938         int nHeight;
939         ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight );
940         SetWindowPos( pFrame->mhWnd, 0,
941                       nX, nY, nWidth, nHeight,
942                       SWP_NOZORDER | SWP_NOACTIVATE );
943     }
944 }
945 
946 // -----------------------------------------------------------------------
947 
948 WinSalFrame::WinSalFrame()
949 {
950     SalData* pSalData = GetSalData();
951 
952     mhWnd               = 0;
953     mhCursor            = LoadCursor( 0, IDC_ARROW );
954     mhDefIMEContext     = 0;
955     mpGraphics          = NULL;
956     mpGraphics2         = NULL;
957     mnShowState         = SW_SHOWNORMAL;
958     mnWidth             = 0;
959     mnHeight            = 0;
960     mnMinWidth          = 0;
961     mnMinHeight         = 0;
962     mnMaxWidth          = SHRT_MAX;
963     mnMaxHeight         = SHRT_MAX;
964     mnInputLang         = 0;
965     mnInputCodePage     = 0;
966     mbGraphics          = FALSE;
967     mbCaption           = FALSE;
968     mbBorder            = FALSE;
969     mbFixBorder         = FALSE;
970     mbSizeBorder        = FALSE;
971     mbFullScreen        = FALSE;
972     mbPresentation      = FALSE;
973     mbInShow            = FALSE;
974     mbRestoreMaximize   = FALSE;
975     mbInMoveMsg         = FALSE;
976     mbInSizeMsg         = FALSE;
977     mbFullScreenToolWin = FALSE;
978     mbDefPos            = TRUE;
979     mbOverwriteState    = TRUE;
980     mbIME               = FALSE;
981     mbHandleIME         = FALSE;
982     mbSpezIME           = FALSE;
983     mbAtCursorIME       = FALSE;
984     mbCandidateMode     = FALSE;
985     mbFloatWin          = FALSE;
986     mbNoIcon            = FALSE;
987     mSelectedhMenu      = 0;
988     mLastActivatedhMenu = 0;
989     mpClipRgnData       = NULL;
990     mbFirstClipRect     = TRUE;
991     mpNextClipRect      = NULL;
992 	mnDisplay			= 0;
993 
994     memset( &maState, 0, sizeof( SalFrameState ) );
995     maSysData.nSize     = sizeof( SystemEnvData );
996 
997     memset( &maGeometry, 0, sizeof( maGeometry ) );
998 
999     // Daten ermitteln, wenn erster Frame angelegt wird
1000     if ( !pSalData->mpFirstFrame )
1001     {
1002         if ( !aSalShlData.mnWheelMsgId )
1003             aSalShlData.mnWheelMsgId = RegisterWindowMessage( MSH_MOUSEWHEEL );
1004         if ( !aSalShlData.mnWheelScrollLines )
1005             aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
1006         if ( !aSalShlData.mnWheelScrollChars )
1007             aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars();
1008     }
1009 
1010     // insert frame in framelist
1011     mpNextFrame = pSalData->mpFirstFrame;
1012     pSalData->mpFirstFrame = this;
1013 }
1014 
1015 // -----------------------------------------------------------------------
1016 void WinSalFrame::updateScreenNumber()
1017 {
1018     if( mnDisplay == -1 ) // spans all monitors
1019         return;
1020     WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
1021     if( pSys )
1022     {
1023         const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
1024             pSys->getMonitors();
1025         Point aPoint( maGeometry.nX, maGeometry.nY );
1026         size_t nMon = rMonitors.size();
1027         for( size_t i = 0; i < nMon; i++ )
1028         {
1029             if( rMonitors[i].m_aArea.IsInside( aPoint ) )
1030             {
1031                 mnDisplay = static_cast<sal_Int32>(i);
1032                 maGeometry.nScreenNumber = static_cast<unsigned int>(i);
1033             }
1034         }
1035     }
1036 }
1037 
1038 // -----------------------------------------------------------------------
1039 
1040 WinSalFrame::~WinSalFrame()
1041 {
1042     SalData* pSalData = GetSalData();
1043 
1044     if( mpClipRgnData )
1045         delete [] (BYTE*)mpClipRgnData;
1046 
1047     // remove frame from framelist
1048     WinSalFrame** ppFrame = &pSalData->mpFirstFrame;
1049     for(; (*ppFrame != this) && *ppFrame; ppFrame = &(*ppFrame)->mpNextFrame );
1050     if( *ppFrame )
1051         *ppFrame = mpNextFrame;
1052     mpNextFrame = NULL;
1053 
1054     // Release Cache DC
1055     if ( mpGraphics2 &&
1056          mpGraphics2->getHDC() )
1057         ReleaseGraphics( mpGraphics2 );
1058 
1059     // destroy saved DC
1060     if ( mpGraphics )
1061     {
1062         if ( mpGraphics->mhDefPal )
1063             SelectPalette( mpGraphics->getHDC(), mpGraphics->mhDefPal, TRUE );
1064         ImplSalDeInitGraphics( mpGraphics );
1065         ReleaseDC( mhWnd, mpGraphics->getHDC() );
1066         delete mpGraphics;
1067         mpGraphics = NULL;
1068     }
1069 
1070     if ( mhWnd )
1071     {
1072         // reset mouse leave data
1073         if ( pSalData->mhWantLeaveMsg == mhWnd )
1074         {
1075             pSalData->mhWantLeaveMsg = 0;
1076             if ( pSalData->mpMouseLeaveTimer )
1077             {
1078                 delete pSalData->mpMouseLeaveTimer;
1079                 pSalData->mpMouseLeaveTimer = NULL;
1080             }
1081         }
1082 
1083         // destroy system frame
1084         if ( !DestroyWindow( mhWnd ) )
1085             SetWindowPtr( mhWnd, 0 );
1086 
1087         mhWnd = 0;
1088     }
1089 }
1090 
1091 // -----------------------------------------------------------------------
1092 
1093 SalGraphics* WinSalFrame::GetGraphics()
1094 {
1095     if ( mbGraphics )
1096         return NULL;
1097 
1098     // Other threads get an own DC, because Windows modify in the
1099     // other case our DC (changing clip region), when they send a
1100     // WM_ERASEBACKGROUND message
1101     SalData* pSalData = GetSalData();
1102     if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
1103     {
1104         // We use only three CacheDC's for all threads, because W9x is limited
1105         // to max. 5 Cache DC's per thread
1106         if ( pSalData->mnCacheDCInUse >= 3 )
1107             return NULL;
1108 
1109         if ( !mpGraphics2 )
1110         {
1111             mpGraphics2 = new WinSalGraphics;
1112             mpGraphics2->setHDC(0);
1113             mpGraphics2->mhWnd       = mhWnd;
1114             mpGraphics2->mbPrinter   = FALSE;
1115             mpGraphics2->mbVirDev    = FALSE;
1116             mpGraphics2->mbWindow    = TRUE;
1117             mpGraphics2->mbScreen    = TRUE;
1118         }
1119 
1120         HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1121                                         SAL_MSG_GETDC,
1122                                         (WPARAM)mhWnd, 0 );
1123         if ( hDC )
1124         {
1125             mpGraphics2->setHDC(hDC);
1126             if ( pSalData->mhDitherPal )
1127             {
1128                 mpGraphics2->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1129                 RealizePalette( hDC );
1130             }
1131             ImplSalInitGraphics( mpGraphics2 );
1132             mbGraphics = TRUE;
1133 
1134             pSalData->mnCacheDCInUse++;
1135             return mpGraphics2;
1136         }
1137         else
1138             return NULL;
1139     }
1140     else
1141     {
1142         if ( !mpGraphics )
1143         {
1144             HDC hDC = GetDC( mhWnd );
1145             if ( hDC )
1146             {
1147                 mpGraphics = new WinSalGraphics;
1148                 mpGraphics->setHDC(hDC);
1149                 mpGraphics->mhWnd     = mhWnd;
1150                 mpGraphics->mbPrinter = FALSE;
1151                 mpGraphics->mbVirDev  = FALSE;
1152                 mpGraphics->mbWindow  = TRUE;
1153                 mpGraphics->mbScreen  = TRUE;
1154                 if ( pSalData->mhDitherPal )
1155                 {
1156                     mpGraphics->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1157                     RealizePalette( hDC );
1158                 }
1159                 ImplSalInitGraphics( mpGraphics );
1160                 mbGraphics = TRUE;
1161             }
1162         }
1163         else
1164             mbGraphics = TRUE;
1165 
1166         return mpGraphics;
1167     }
1168 }
1169 
1170 // -----------------------------------------------------------------------
1171 
1172 void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
1173 {
1174     if ( mpGraphics2 == pGraphics )
1175     {
1176         if ( mpGraphics2->getHDC() )
1177         {
1178             SalData* pSalData = GetSalData();
1179             if ( mpGraphics2->mhDefPal )
1180                 SelectPalette( mpGraphics2->getHDC(), mpGraphics2->mhDefPal, TRUE );
1181             ImplSalDeInitGraphics( mpGraphics2 );
1182             ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1183                              SAL_MSG_RELEASEDC,
1184                              (WPARAM)mhWnd,
1185                              (LPARAM)mpGraphics2->getHDC() );
1186             mpGraphics2->setHDC(0);
1187             pSalData->mnCacheDCInUse--;
1188         }
1189     }
1190 
1191     mbGraphics = FALSE;
1192 }
1193 
1194 // -----------------------------------------------------------------------
1195 
1196 sal_Bool WinSalFrame::PostEvent( void* pData )
1197 {
1198     return (sal_Bool)ImplPostMessage( mhWnd, SAL_MSG_USEREVENT, 0, (LPARAM)pData );
1199 }
1200 
1201 // -----------------------------------------------------------------------
1202 
1203 void WinSalFrame::SetTitle( const XubString& rTitle )
1204 {
1205     DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::SetTitle(): WCHAR != sal_Unicode" );
1206 
1207     if ( !SetWindowTextW( mhWnd, reinterpret_cast<LPCWSTR>(rTitle.GetBuffer()) ) )
1208     {
1209         ByteString aAnsiTitle = ImplSalGetWinAnsiString( rTitle );
1210         SetWindowTextA( mhWnd, aAnsiTitle.GetBuffer() );
1211     }
1212 }
1213 
1214 // -----------------------------------------------------------------------
1215 
1216 void WinSalFrame::SetIcon( sal_uInt16 nIcon )
1217 {
1218     // If we have a window without an Icon (for example a dialog), ignore this call
1219     if ( mbNoIcon )
1220         return;
1221 
1222     // 0 means default (class) icon
1223     HICON hIcon = NULL, hSmIcon = NULL;
1224     if ( !nIcon )
1225         nIcon = 1;
1226 
1227     ImplLoadSalIcon( nIcon, hIcon, hSmIcon );
1228 
1229     DBG_ASSERT( hIcon ,   "WinSalFrame::SetIcon(): Could not load large icon !" );
1230     DBG_ASSERT( hSmIcon , "WinSalFrame::SetIcon(): Could not load small icon !" );
1231 
1232     ImplSendMessage( mhWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );
1233     ImplSendMessage( mhWnd, WM_SETICON, ICON_SMALL, (LPARAM)hSmIcon );
1234 }
1235 
1236 // -----------------------------------------------------------------------
1237 
1238 void WinSalFrame::SetMenu( SalMenu* pSalMenu )
1239 {
1240     WinSalMenu* pWMenu = static_cast<WinSalMenu*>(pSalMenu);
1241     if( pSalMenu && pWMenu->mbMenuBar )
1242         ::SetMenu( mhWnd, pWMenu->mhMenu );
1243 }
1244 
1245 void WinSalFrame::DrawMenuBar()
1246 {
1247     ::DrawMenuBar( mhWnd );
1248 }
1249 
1250 // -----------------------------------------------------------------------
1251 HWND ImplGetParentHwnd( HWND hWnd )
1252 {
1253     WinSalFrame* pFrame = GetWindowPtr( hWnd );
1254 	if( !pFrame || !pFrame->GetWindow())
1255 		return ::GetParent( hWnd );
1256 	Window *pRealParent = pFrame->GetWindow()->ImplGetWindowImpl()->mpRealParent;
1257 	if( pRealParent )
1258 		return static_cast<WinSalFrame*>(pRealParent->ImplGetWindowImpl()->mpFrame)->mhWnd;
1259 	else
1260 		return ::GetParent( hWnd );
1261 
1262 }
1263 
1264 // -----------------------------------------------------------------------
1265 
1266 SalFrame* WinSalFrame::GetParent() const
1267 {
1268     return GetWindowPtr( ImplGetParentHwnd( mhWnd ) );
1269 }
1270 
1271 // -----------------------------------------------------------------------
1272 
1273 static void ImplSalShow( HWND hWnd, sal_Bool bVisible, sal_Bool bNoActivate )
1274 {
1275     WinSalFrame* pFrame = GetWindowPtr( hWnd );
1276     if ( !pFrame )
1277         return;
1278 
1279     if ( bVisible )
1280     {
1281         pFrame->mbDefPos = FALSE;
1282         pFrame->mbOverwriteState = TRUE;
1283         pFrame->mbInShow = TRUE;
1284 
1285         // #i4715, save position
1286         RECT aRectPreMatrox, aRectPostMatrox;
1287         GetWindowRect( hWnd, &aRectPreMatrox );
1288 
1289         vcl::DeletionListener aDogTag( pFrame );
1290         if( bNoActivate )
1291             ShowWindow( hWnd, SW_SHOWNOACTIVATE );
1292         else
1293             ShowWindow( hWnd, pFrame->mnShowState );
1294         if( aDogTag.isDeleted() )
1295             return;
1296 
1297         if ( aSalShlData.mbWXP && pFrame->mbFloatWin && !(pFrame->mnStyle & SAL_FRAME_STYLE_NOSHADOW))
1298         {
1299             // erase the window immediately to improve XP shadow effect
1300             // otherwise the shadow may appears long time before the rest of the window
1301             // especially when accessibility is on
1302             HDC dc = GetDC( hWnd );
1303             RECT aRect;
1304             GetClientRect( hWnd, &aRect );
1305             FillRect( dc, &aRect, (HBRUSH) (COLOR_MENU+1) ); // choose the menucolor, because its mostly noticeable for menues
1306             ReleaseDC( hWnd, dc );
1307         }
1308 
1309         // #i4715, matrox centerpopup might have changed our position
1310         // reposition popups without caption (menues, dropdowns, tooltips)
1311         GetWindowRect( hWnd, &aRectPostMatrox );
1312         if( (GetWindowStyle( hWnd ) & WS_POPUP) &&
1313             !pFrame->mbCaption &&
1314             (aRectPreMatrox.left != aRectPostMatrox.left || aRectPreMatrox.top != aRectPostMatrox.top) )
1315             SetWindowPos( hWnd, 0, aRectPreMatrox.left, aRectPreMatrox.top, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE  );
1316 
1317         if( aDogTag.isDeleted() )
1318             return;
1319 		Window *pClientWin = pFrame->GetWindow()->ImplGetClientWindow();
1320         if ( pFrame->mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
1321             pFrame->mnShowState = SW_SHOWNOACTIVATE;
1322         else
1323             pFrame->mnShowState = SW_SHOW;
1324         // Damit Taskleiste unter W98 auch gleich ausgeblendet wird
1325         if ( pFrame->mbPresentation )
1326         {
1327             HWND hWndParent = ::GetParent( hWnd );
1328             if ( hWndParent )
1329                 SetForegroundWindow( hWndParent );
1330             SetForegroundWindow( hWnd );
1331         }
1332 
1333         pFrame->mbInShow = FALSE;
1334         pFrame->updateScreenNumber();
1335 
1336         // Direct Paint only, if we get the SolarMutx
1337         if ( ImplSalYieldMutexTryToAcquire() )
1338         {
1339             UpdateWindow( hWnd );
1340             ImplSalYieldMutexRelease();
1341         }
1342     }
1343     else
1344     {
1345         // See also Bug #91813# and #68467#
1346         if ( pFrame->mbFullScreen &&
1347              pFrame->mbPresentation &&
1348              (aSalShlData.mnVersion < 500) &&
1349              !::GetParent( hWnd ) )
1350         {
1351             // Damit im Impress-Player in der Taskleiste nicht durch
1352             // einen Windows-Fehler hin- und wieder mal ein leerer
1353             // Button stehen bleibt, muessen wir hier die Taskleiste
1354             // etwas austricksen. Denn wenn wir im FullScreenMode sind
1355             // und das Fenster hiden kommt Windows anscheinend etwas aus
1356             // dem tritt und somit minimieren wir das Fenster damit es
1357             // nicht flackert
1358             ANIMATIONINFO aInfo;
1359             aInfo.cbSize = sizeof( aInfo );
1360             SystemParametersInfo( SPI_GETANIMATION, 0, &aInfo, 0 );
1361             if ( aInfo.iMinAnimate )
1362             {
1363                 int nOldAni = aInfo.iMinAnimate;
1364                 aInfo.iMinAnimate = 0;
1365                 SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 );
1366                 ShowWindow( pFrame->mhWnd, SW_SHOWMINNOACTIVE );
1367                 aInfo.iMinAnimate = nOldAni;
1368                 SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 );
1369             }
1370             else
1371                 ShowWindow( hWnd, SW_SHOWMINNOACTIVE );
1372             ShowWindow( hWnd, SW_HIDE );
1373         }
1374         else
1375             ShowWindow( hWnd, SW_HIDE );
1376     }
1377 }
1378 
1379 // -----------------------------------------------------------------------
1380 
1381 
1382 void WinSalFrame::SetExtendedFrameStyle( SalExtStyle )
1383 {
1384 }
1385 
1386 // -----------------------------------------------------------------------
1387 
1388 void WinSalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate )
1389 {
1390     // Post this Message to the window, because this only works
1391     // in the thread of the window, which has create this window.
1392     // We post this message to avoid deadlocks
1393     if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
1394         ImplPostMessage( mhWnd, SAL_MSG_SHOW, bVisible, bNoActivate );
1395     else
1396         ImplSalShow( mhWnd, bVisible, bNoActivate );
1397 }
1398 
1399 // -----------------------------------------------------------------------
1400 
1401 void WinSalFrame::Enable( sal_Bool bEnable )
1402 {
1403     EnableWindow( mhWnd, bEnable );
1404 }
1405 
1406 // -----------------------------------------------------------------------
1407 
1408 void WinSalFrame::SetMinClientSize( long nWidth, long nHeight )
1409 {
1410     mnMinWidth  = nWidth;
1411     mnMinHeight = nHeight;
1412 }
1413 
1414 void WinSalFrame::SetMaxClientSize( long nWidth, long nHeight )
1415 {
1416     mnMaxWidth  = nWidth;
1417     mnMaxHeight = nHeight;
1418 }
1419 
1420 // -----------------------------------------------------------------------
1421 
1422 void WinSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight,
1423                                                    sal_uInt16 nFlags )
1424 {
1425     sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
1426     if ( !bVisible )
1427     {
1428 		Window *pClientWin = GetWindow()->ImplGetClientWindow();
1429         if ( mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
1430                 mnShowState = SW_SHOWNOACTIVATE;
1431         else
1432                 mnShowState = SW_SHOWNORMAL;
1433     }
1434     else
1435     {
1436         if ( IsIconic( mhWnd ) || IsZoomed( mhWnd ) )
1437                 ShowWindow( mhWnd, SW_RESTORE );
1438     }
1439 
1440     sal_uInt16 nEvent = 0;
1441     UINT    nPosSize = 0;
1442     RECT    aClientRect, aWindowRect;
1443     GetClientRect( mhWnd, &aClientRect );   // x,y always 0,0, but width and height without border
1444     GetWindowRect( mhWnd, &aWindowRect );   // x,y in screen coordinates, width and height with border
1445 
1446     if ( !(nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) )
1447         nPosSize |= SWP_NOMOVE;
1448     else
1449     {
1450         //DBG_ASSERT( nX && nY, " Windowposition of (0,0) requested!" );
1451         nEvent = SALEVENT_MOVE;
1452     }
1453     if ( !(nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) )
1454         nPosSize |= SWP_NOSIZE;
1455     else
1456         nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
1457 
1458     if ( !(nFlags & SAL_FRAME_POSSIZE_X) )
1459         nX = aWindowRect.left;
1460     if ( !(nFlags & SAL_FRAME_POSSIZE_Y) )
1461         nY = aWindowRect.top;
1462     if ( !(nFlags & SAL_FRAME_POSSIZE_WIDTH) )
1463         nWidth = aClientRect.right-aClientRect.left;
1464     if ( !(nFlags & SAL_FRAME_POSSIZE_HEIGHT) )
1465         nHeight = aClientRect.bottom-aClientRect.top;
1466 
1467     // Calculate window size including the border
1468     RECT    aWinRect;
1469     aWinRect.left   = 0;
1470     aWinRect.right  = (int)nWidth-1;
1471     aWinRect.top    = 0;
1472     aWinRect.bottom = (int)nHeight-1;
1473     AdjustWindowRectEx( &aWinRect, GetWindowStyle( mhWnd ),
1474                         FALSE,     GetWindowExStyle( mhWnd ) );
1475     nWidth  = aWinRect.right - aWinRect.left + 1;
1476     nHeight = aWinRect.bottom - aWinRect.top + 1;
1477 
1478     if ( !(nPosSize & SWP_NOMOVE) && ::GetParent( mhWnd ) )
1479     {
1480             // --- RTL --- (mirror window pos)
1481             RECT aParentRect;
1482             GetClientRect( ImplGetParentHwnd( mhWnd ), &aParentRect );
1483             if( Application::GetSettings().GetLayoutRTL() )
1484                 nX = (aParentRect.right - aParentRect.left) - nWidth-1 - nX;
1485 
1486             //#110386#, do not transform coordinates for system child windows
1487             if( !(GetWindowStyle( mhWnd ) & WS_CHILD) )
1488             {
1489                 POINT aPt;
1490                 aPt.x = nX;
1491                 aPt.y = nY;
1492 
1493                 HWND parentHwnd = ImplGetParentHwnd( mhWnd );
1494                 WinSalFrame* pParentFrame = GetWindowPtr( parentHwnd );
1495                 if ( pParentFrame && pParentFrame->mnShowState == SW_SHOWMAXIMIZED )
1496                 {
1497                     // #i42485#: parent will be shown maximized in which case
1498                     // a ClientToScreen uses the wrong coordinates (i.e. those from the restore pos)
1499                     // so use the (already updated) frame geometry for the transformation
1500                     aPt.x +=  pParentFrame->maGeometry.nX;
1501                     aPt.y +=  pParentFrame->maGeometry.nY;
1502                 }
1503                 else
1504                     ClientToScreen( parentHwnd, &aPt );
1505 
1506                 nX = aPt.x;
1507                 nY = aPt.y;
1508             }
1509     }
1510 
1511     // #i3338# to be conformant to UNIX we must position the client window, ie without the decoration
1512     // #i43250# if the position was read from the system (GetWindowRect(), see above), it must not be modified
1513     if ( nFlags & SAL_FRAME_POSSIZE_X )
1514         nX += aWinRect.left;
1515     if ( nFlags & SAL_FRAME_POSSIZE_Y )
1516         nY += aWinRect.top;
1517 
1518     int     nScreenX;
1519     int     nScreenY;
1520     int     nScreenWidth;
1521     int     nScreenHeight;
1522 
1523 
1524     RECT aRect;
1525     ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1526     nScreenX        = aRect.left;
1527     nScreenY        = aRect.top;
1528     nScreenWidth    = aRect.right-aRect.left;
1529     nScreenHeight   = aRect.bottom-aRect.top;
1530 
1531     if ( mbDefPos && (nPosSize & SWP_NOMOVE)) // we got no positioning request, so choose default position
1532     {
1533         // center window
1534 
1535         HWND hWndParent = ::GetParent( mhWnd );
1536         // Search for TopLevel Frame
1537         while ( hWndParent && (GetWindowStyle( hWndParent ) & WS_CHILD) )
1538             hWndParent = ::GetParent( hWndParent );
1539         // if the Window has a Parent, than center the window to
1540         // the parent, in the other case to the screen
1541         if ( hWndParent && !IsIconic( hWndParent ) &&
1542              (GetWindowStyle( hWndParent ) & WS_VISIBLE) )
1543         {
1544             RECT aParentRect;
1545             GetWindowRect( hWndParent, &aParentRect );
1546             int nParentWidth    = aParentRect.right-aParentRect.left;
1547             int nParentHeight   = aParentRect.bottom-aParentRect.top;
1548 
1549             // We don't center, when Parent is smaller than our window
1550             if ( (nParentWidth-GetSystemMetrics( SM_CXFIXEDFRAME ) <= nWidth) &&
1551                  (nParentHeight-GetSystemMetrics( SM_CYFIXEDFRAME ) <= nHeight) )
1552             {
1553                 int nOff = GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
1554                 nX = aParentRect.left+nOff;
1555                 nY = aParentRect.top+nOff;
1556             }
1557             else
1558             {
1559                 nX = (nParentWidth-nWidth)/2 + aParentRect.left;
1560                 nY = (nParentHeight-nHeight)/2 + aParentRect.top;
1561             }
1562         }
1563         else
1564         {
1565             POINT pt;
1566             GetCursorPos( &pt );
1567             RECT aRect;
1568             aRect.left = pt.x;
1569             aRect.top = pt.y;
1570             aRect.right = pt.x+2;
1571             aRect.bottom = pt.y+2;
1572 
1573             // dualmonitor support:
1574             // Get screensize of the monitor whith the mouse pointer
1575             ImplSalGetWorkArea( mhWnd, &aRect, &aRect );
1576 
1577             nX = ((aRect.right-aRect.left)-nWidth)/2 + aRect.left;
1578             nY = ((aRect.bottom-aRect.top)-nHeight)/2 + aRect.top;
1579         }
1580 
1581 
1582         //if ( bVisible )
1583         //    mbDefPos = FALSE;
1584 
1585         mbDefPos = FALSE;   // center only once
1586         nPosSize &= ~SWP_NOMOVE;        // activate positioning
1587         nEvent = SALEVENT_MOVERESIZE;
1588     }
1589 
1590 
1591     // Adjust Window in the screen
1592     sal_Bool bCheckOffScreen = TRUE;
1593 
1594     // but don't do this for floaters or ownerdraw windows that are currently moved interactively
1595     if( (mnStyle & SAL_FRAME_STYLE_FLOAT) && !(mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
1596         bCheckOffScreen = FALSE;
1597 
1598     if( mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
1599     {
1600         // may be the window is currently being moved (mouse is captured), then no check is required
1601         if( mhWnd == ::GetCapture() )
1602             bCheckOffScreen = FALSE;
1603         else
1604             bCheckOffScreen = TRUE;
1605     }
1606 
1607     if( bCheckOffScreen )
1608     {
1609         if ( nX+nWidth > nScreenX+nScreenWidth )
1610             nX = (nScreenX+nScreenWidth) - nWidth;
1611         if ( nY+nHeight > nScreenY+nScreenHeight )
1612             nY = (nScreenY+nScreenHeight) - nHeight;
1613         if ( nX < nScreenX )
1614             nX = nScreenX;
1615         if ( nY < nScreenY )
1616             nY = nScreenY;
1617     }
1618 
1619     UINT nPosFlags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | nPosSize;
1620     // bring floating windows always to top
1621     if( !(mnStyle & SAL_FRAME_STYLE_FLOAT) )
1622         nPosFlags |= SWP_NOZORDER; // do not change z-order
1623 
1624     SetWindowPos( mhWnd, HWND_TOP, nX, nY, (int)nWidth, (int)nHeight, nPosFlags  );
1625 
1626 	UpdateFrameGeometry( mhWnd, this );
1627 
1628     // Notification -- really ???
1629     if( nEvent )
1630         CallCallback( nEvent, NULL );
1631 }
1632 
1633 // -----------------------------------------------------------------------
1634 
1635 static void ImplSetParentFrame( WinSalFrame* pThis, HWND hNewParentWnd, sal_Bool bAsChild )
1636 {
1637     // save hwnd, will be overwritten in WM_CREATE during createwindow
1638     HWND hWndOld = pThis->mhWnd;
1639     HWND hWndOldParent = ::GetParent( hWndOld );
1640     SalData* pSalData = GetSalData();
1641 
1642     if( hNewParentWnd == hWndOldParent )
1643         return;
1644 
1645     ::std::vector< WinSalFrame* > children;
1646     ::std::vector< WinSalObject* > systemChildren;
1647 
1648     // search child windows
1649     WinSalFrame *pFrame = pSalData->mpFirstFrame;
1650     while( pFrame )
1651     {
1652         HWND hWndParent = ::GetParent( pFrame->mhWnd );
1653         if( pThis->mhWnd == hWndParent )
1654             children.push_back( pFrame );
1655         pFrame = pFrame->mpNextFrame;
1656     }
1657 
1658     // search system child windows (plugins etc.)
1659     WinSalObject *pObject = pSalData->mpFirstObject;
1660     while( pObject )
1661     {
1662         HWND hWndParent = ::GetParent( pObject->mhWnd );
1663         if( pThis->mhWnd == hWndParent )
1664             systemChildren.push_back( pObject );
1665         pObject = pObject->mpNextObject;
1666     }
1667 
1668     sal_Bool bNeedGraphics = pThis->mbGraphics;
1669     sal_Bool bNeedCacheDC  = FALSE;
1670 
1671     HFONT   hFont   = NULL;
1672     HPEN    hPen    = NULL;
1673     HBRUSH  hBrush  = NULL;
1674 
1675     #if OSL_DEBUG_LEVEL > 0
1676     int oldCount = pSalData->mnCacheDCInUse;
1677 	(void)oldCount;
1678     #endif
1679 
1680     // Release Cache DC
1681     if ( pThis->mpGraphics2 &&
1682          pThis->mpGraphics2->getHDC() )
1683     {
1684         // save current gdi objects before hdc is gone
1685         hFont   = (HFONT)   GetCurrentObject( pThis->mpGraphics2->getHDC(), OBJ_FONT);
1686         hPen    = (HPEN)    GetCurrentObject( pThis->mpGraphics2->getHDC(), OBJ_PEN);
1687         hBrush  = (HBRUSH)  GetCurrentObject( pThis->mpGraphics2->getHDC(), OBJ_BRUSH);
1688         pThis->ReleaseGraphics( pThis->mpGraphics2 );
1689 
1690         // recreate cache dc only if it was destroyed
1691         bNeedCacheDC  = TRUE;
1692     }
1693 
1694     // destroy saved DC
1695     if ( pThis->mpGraphics )
1696     {
1697         if ( pThis->mpGraphics->mhDefPal )
1698             SelectPalette( pThis->mpGraphics->getHDC(), pThis->mpGraphics->mhDefPal, TRUE );
1699         ImplSalDeInitGraphics( pThis->mpGraphics );
1700         ReleaseDC( pThis->mhWnd, pThis->mpGraphics->getHDC() );
1701     }
1702 
1703     // create a new hwnd with the same styles
1704     HWND hWndParent = hNewParentWnd;
1705     // forward to main thread
1706     HWND hWnd = (HWND) ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1707                                         bAsChild ? SAL_MSG_RECREATECHILDHWND : SAL_MSG_RECREATEHWND,
1708                                         (WPARAM) hWndParent, (LPARAM)pThis->mhWnd );
1709 
1710     // succeeded ?
1711     DBG_ASSERT( IsWindow( hWnd ), "WinSalFrame::SetParent not successful");
1712 
1713     // recreate DCs
1714     if( bNeedGraphics )
1715     {
1716         if( pThis->mpGraphics2 )
1717         {
1718             pThis->mpGraphics2->mhWnd = hWnd;
1719 
1720             if( bNeedCacheDC )
1721             {
1722                 // re-create cached DC
1723                 HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->mhComWnd,
1724                                                 SAL_MSG_GETDC,
1725                                                 (WPARAM) hWnd, 0 );
1726                 if ( hDC )
1727                 {
1728                     pThis->mpGraphics2->setHDC(hDC);
1729                     if ( pSalData->mhDitherPal )
1730                     {
1731                         pThis->mpGraphics2->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
1732                         RealizePalette( hDC );
1733                     }
1734                     ImplSalInitGraphics( pThis->mpGraphics2 );
1735 
1736                     // re-select saved gdi objects
1737                     if( hFont )
1738                         SelectObject( hDC, hFont );
1739                     if( hPen )
1740                         SelectObject( hDC, hPen );
1741                     if( hBrush )
1742                         SelectObject( hDC, hBrush );
1743 
1744                     pThis->mbGraphics = TRUE;
1745 
1746                     pSalData->mnCacheDCInUse++;
1747 
1748                     DBG_ASSERT( oldCount == pSalData->mnCacheDCInUse, "WinSalFrame::SetParent() hDC count corrupted");
1749                 }
1750             }
1751         }
1752 
1753         if( pThis->mpGraphics )
1754         {
1755             // re-create DC
1756             pThis->mpGraphics->mhWnd = hWnd;
1757             pThis->mpGraphics->setHDC( GetDC( hWnd ) );
1758             if ( GetSalData()->mhDitherPal )
1759             {
1760                 pThis->mpGraphics->mhDefPal = SelectPalette( pThis->mpGraphics->getHDC(), GetSalData()->mhDitherPal, TRUE );
1761                 RealizePalette( pThis->mpGraphics->getHDC() );
1762             }
1763             ImplSalInitGraphics( pThis->mpGraphics );
1764             pThis->mbGraphics = TRUE;
1765         }
1766     }
1767 
1768 
1769     // TODO: add SetParent() call for SalObjects
1770     DBG_ASSERT( systemChildren.empty(), "WinSalFrame::SetParent() parent of living system child window will be destroyed!");
1771 
1772     // reparent children before old parent is destroyed
1773     for( ::std::vector< WinSalFrame* >::iterator iChild = children.begin(); iChild != children.end(); iChild++ )
1774         ImplSetParentFrame( *iChild, hWnd, FALSE );
1775 
1776     children.clear();
1777     systemChildren.clear();
1778 
1779     // Now destroy original HWND in the thread where it was created.
1780     ImplSendMessage( GetSalData()->mpFirstInstance->mhComWnd,
1781                      SAL_MSG_DESTROYHWND, (WPARAM) 0, (LPARAM)hWndOld);
1782 }
1783 
1784 // -----------------------------------------------------------------------
1785 
1786 void WinSalFrame::SetParent( SalFrame* pNewParent )
1787 {
1788     WinSalFrame::mbInReparent = TRUE;
1789     ImplSetParentFrame( this, static_cast<WinSalFrame*>(pNewParent)->mhWnd, FALSE );
1790     WinSalFrame::mbInReparent = FALSE;
1791 }
1792 
1793 bool WinSalFrame::SetPluginParent( SystemParentData* pNewParent )
1794 {
1795     if ( pNewParent->hWnd == 0 )
1796     {
1797         pNewParent->hWnd = GetDesktopWindow();
1798     }
1799 
1800     WinSalFrame::mbInReparent = TRUE;
1801     ImplSetParentFrame( this, pNewParent->hWnd, TRUE );
1802     WinSalFrame::mbInReparent = FALSE;
1803     return true;
1804 }
1805 
1806 
1807 // -----------------------------------------------------------------------
1808 
1809 void WinSalFrame::GetWorkArea( Rectangle &rRect )
1810 {
1811     RECT aRect;
1812 	ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1813     rRect.nLeft     = aRect.left;
1814     rRect.nRight    = aRect.right-1;
1815     rRect.nTop      = aRect.top;
1816     rRect.nBottom   = aRect.bottom-1;
1817 }
1818 
1819 // -----------------------------------------------------------------------
1820 
1821 void WinSalFrame::GetClientSize( long& rWidth, long& rHeight )
1822 {
1823     rWidth  = maGeometry.nWidth;
1824     rHeight = maGeometry.nHeight;
1825 }
1826 
1827 // -----------------------------------------------------------------------
1828 
1829 void WinSalFrame::SetWindowState( const SalFrameState* pState )
1830 {
1831     // Wir testen, ob das Fenster ueberhaupt auf den Bildschirm passt, damit
1832     // nicht wenn die Bildschirm-Aufloesung geaendert wurde, das Fenster aus
1833     // diesem herausragt
1834     int     nX;
1835     int     nY;
1836     int     nWidth;
1837     int     nHeight;
1838     int     nScreenX;
1839     int     nScreenY;
1840     int     nScreenWidth;
1841     int     nScreenHeight;
1842 
1843     RECT aRect;
1844 	ImplSalGetWorkArea( mhWnd, &aRect, NULL );
1845     // #102500# allow some overlap, the window could have been made a little larger than the physical screen
1846     nScreenX        = aRect.left-10;
1847     nScreenY        = aRect.top-10;
1848     nScreenWidth    = aRect.right-aRect.left+20;
1849     nScreenHeight   = aRect.bottom-aRect.top+20;
1850 
1851     UINT    nPosSize    = 0;
1852     RECT    aWinRect;
1853     GetWindowRect( mhWnd, &aWinRect );
1854 
1855     // to be consistent with Unix, the frame state is without(!) decoration
1856     // ->add the decoration
1857     RECT aRect2 = aWinRect;
1858 	AdjustWindowRectEx( &aRect2, GetWindowStyle( mhWnd ),
1859 					FALSE,     GetWindowExStyle( mhWnd ) );
1860     long nTopDeco = abs( aWinRect.top - aRect2.top );
1861     long nLeftDeco = abs( aWinRect.left - aRect2.left );
1862     long nBottomDeco = abs( aWinRect.bottom - aRect2.bottom );
1863     long nRightDeco = abs( aWinRect.right - aRect2.right );
1864 
1865     // Fenster-Position/Groesse in den Bildschirm einpassen
1866     if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y)) )
1867         nPosSize |= SWP_NOMOVE;
1868     if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)) )
1869         nPosSize |= SWP_NOSIZE;
1870     if ( pState->mnMask & SAL_FRAMESTATE_MASK_X )
1871         nX = (int)pState->mnX - nLeftDeco;
1872     else
1873         nX = aWinRect.left;
1874     if ( pState->mnMask & SAL_FRAMESTATE_MASK_Y )
1875         nY = (int)pState->mnY - nTopDeco;
1876     else
1877         nY = aWinRect.top;
1878     if ( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH )
1879         nWidth = (int)pState->mnWidth + nLeftDeco + nRightDeco;
1880     else
1881         nWidth = aWinRect.right-aWinRect.left;
1882     if ( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT )
1883         nHeight = (int)pState->mnHeight + nTopDeco + nBottomDeco;
1884     else
1885         nHeight = aWinRect.bottom-aWinRect.top;
1886 
1887     // Adjust Window in the screen:
1888     // if it does not fit into the screen do nothing, ie default pos/size will be used
1889     // if there is an overlap with the screen border move the window while keeping its size
1890 
1891     if( nWidth > nScreenWidth || nHeight > nScreenHeight )
1892         nPosSize |= (SWP_NOMOVE | SWP_NOSIZE);
1893 
1894     if ( nX+nWidth > nScreenX+nScreenWidth )
1895         nX = (nScreenX+nScreenWidth) - nWidth;
1896     if ( nY+nHeight > nScreenY+nScreenHeight )
1897         nY = (nScreenY+nScreenHeight) - nHeight;
1898     if ( nX < nScreenX )
1899         nX = nScreenX;
1900     if ( nY < nScreenY )
1901         nY = nScreenY;
1902 
1903     // Restore-Position setzen
1904     WINDOWPLACEMENT aPlacement;
1905     aPlacement.length = sizeof( aPlacement );
1906     GetWindowPlacement( mhWnd, &aPlacement );
1907 
1908     // Status setzen
1909     sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
1910 	sal_Bool bUpdateHiddenFramePos = FALSE;
1911     if ( !bVisible )
1912     {
1913         aPlacement.showCmd = SW_HIDE;
1914 
1915         if ( mbOverwriteState )
1916         {
1917             if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
1918             {
1919                 if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
1920                     mnShowState = SW_SHOWMINIMIZED;
1921                 else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1922 				{
1923                     mnShowState = SW_SHOWMAXIMIZED;
1924 					bUpdateHiddenFramePos = TRUE;
1925 				}
1926                 else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
1927                     mnShowState = SW_SHOWNORMAL;
1928             }
1929         }
1930     }
1931     else
1932     {
1933         if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
1934         {
1935             if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
1936             {
1937                 if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1938                     aPlacement.flags |= WPF_RESTORETOMAXIMIZED;
1939                 aPlacement.showCmd = SW_SHOWMINIMIZED;
1940             }
1941             else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
1942                 aPlacement.showCmd = SW_SHOWMAXIMIZED;
1943             else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
1944                 aPlacement.showCmd = SW_RESTORE;
1945         }
1946     }
1947 
1948     // if a window is neither minimized nor maximized or need not be
1949     // positioned visibly (that is in visible state), do not use
1950     // SetWindowPlacement since it calculates including the TaskBar
1951     if ( !IsIconic( mhWnd ) && !IsZoomed( mhWnd ) &&
1952          (!bVisible || (aPlacement.showCmd == SW_RESTORE)) )
1953     {
1954 		if( bUpdateHiddenFramePos )
1955 		{
1956 		    RECT aStateRect;
1957 		    aStateRect.left   = nX;
1958 		    aStateRect.top    = nY;
1959 		    aStateRect.right  = nX+nWidth;
1960 		    aStateRect.bottom = nY+nHeight;
1961 			// #96084 set a useful internal window size because
1962 			// the window will not be maximized (and the size updated) before show()
1963             SetMaximizedFrameGeometry( mhWnd, this, &aStateRect );
1964 			SetWindowPos( mhWnd, 0,
1965                           maGeometry.nX, maGeometry.nY, maGeometry.nWidth, maGeometry.nHeight,
1966                           SWP_NOZORDER | SWP_NOACTIVATE | nPosSize );
1967 		}
1968 		else
1969 			SetWindowPos( mhWnd, 0,
1970                       nX, nY, nWidth, nHeight,
1971                       SWP_NOZORDER | SWP_NOACTIVATE | nPosSize );
1972     }
1973     else
1974     {
1975         if( !(nPosSize & (SWP_NOMOVE|SWP_NOSIZE)) )
1976         {
1977             aPlacement.rcNormalPosition.left    = nX-nScreenX;
1978             aPlacement.rcNormalPosition.top     = nY-nScreenY;
1979             aPlacement.rcNormalPosition.right   = nX+nWidth-nScreenX;
1980             aPlacement.rcNormalPosition.bottom  = nY+nHeight-nScreenY;
1981         }
1982         SetWindowPlacement( mhWnd, &aPlacement );
1983     }
1984 
1985     if( !(nPosSize & SWP_NOMOVE) )
1986         mbDefPos = FALSE; // window was positioned
1987 }
1988 
1989 // -----------------------------------------------------------------------
1990 
1991 sal_Bool WinSalFrame::GetWindowState( SalFrameState* pState )
1992 {
1993     if ( maState.mnWidth && maState.mnHeight )
1994     {
1995         *pState = maState;
1996         // #94144# allow Minimize again, should be masked out when read from configuration
1997         // 91625 - Don't save minimize
1998         //if ( !(pState->mnState & SAL_FRAMESTATE_MAXIMIZED) )
1999         if ( !(pState->mnState & (SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED)) )
2000             pState->mnState |= SAL_FRAMESTATE_NORMAL;
2001         return TRUE;
2002     }
2003 
2004     return FALSE;
2005 }
2006 
2007 // -----------------------------------------------------------------------
2008 
2009 void WinSalFrame::SetScreenNumber( unsigned int nNewScreen )
2010 {
2011     WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
2012     if( pSys )
2013     {
2014         const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
2015             pSys->getMonitors();
2016         size_t nMon = rMonitors.size();
2017         if( nNewScreen < nMon )
2018         {
2019             Point aOldMonPos, aNewMonPos( rMonitors[nNewScreen].m_aArea.TopLeft() );
2020             Point aCurPos( maGeometry.nX, maGeometry.nY );
2021             for( size_t i = 0; i < nMon; i++ )
2022             {
2023                 if( rMonitors[i].m_aArea.IsInside( aCurPos ) )
2024                 {
2025                     aOldMonPos = rMonitors[i].m_aArea.TopLeft();
2026                     break;
2027                 }
2028             }
2029             mnDisplay = nNewScreen;
2030             maGeometry.nScreenNumber = nNewScreen;
2031             SetPosSize( aNewMonPos.X() + (maGeometry.nX - aOldMonPos.X()),
2032                         aNewMonPos.Y() + (maGeometry.nY - aOldMonPos.Y()),
2033                         0, 0,
2034                         SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
2035         }
2036     }
2037 }
2038 
2039 // -----------------------------------------------------------------------
2040 
2041 void WinSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay )
2042 {
2043     if ( (mbFullScreen == bFullScreen) && (!bFullScreen || (mnDisplay == nDisplay)) )
2044         return;
2045 
2046     mbFullScreen = bFullScreen;
2047 	mnDisplay = nDisplay;
2048 
2049 	if ( bFullScreen )
2050     {
2051         // Damit Taskleiste von Windows ausgeblendet wird
2052         DWORD nExStyle = GetWindowExStyle( mhWnd );
2053         if ( nExStyle & WS_EX_TOOLWINDOW )
2054         {
2055             mbFullScreenToolWin = TRUE;
2056             nExStyle &= ~WS_EX_TOOLWINDOW;
2057             SetWindowExStyle( mhWnd, nExStyle );
2058         }
2059         // save old position
2060         GetWindowRect( mhWnd, &maFullScreenRect );
2061 
2062         // save show state
2063         mnFullScreenShowState = mnShowState;
2064         if ( !(GetWindowStyle( mhWnd ) & WS_VISIBLE) )
2065             mnShowState = SW_SHOW;
2066 
2067         // set window to screen size
2068         ImplSalFrameFullScreenPos( this, TRUE );
2069     }
2070     else
2071     {
2072         // wenn ShowState wieder hergestellt werden muss, hiden wir zuerst
2073         // das Fenster, damit es nicht so sehr flackert
2074         sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
2075         if ( bVisible && (mnShowState != mnFullScreenShowState) )
2076             ShowWindow( mhWnd, SW_HIDE );
2077 
2078         if ( mbFullScreenToolWin )
2079             SetWindowExStyle( mhWnd, GetWindowExStyle( mhWnd ) | WS_EX_TOOLWINDOW );
2080         mbFullScreenToolWin = FALSE;
2081 
2082         SetWindowPos( mhWnd, 0,
2083                       maFullScreenRect.left,
2084                       maFullScreenRect.top,
2085                       maFullScreenRect.right-maFullScreenRect.left,
2086                       maFullScreenRect.bottom-maFullScreenRect.top,
2087                       SWP_NOZORDER | SWP_NOACTIVATE );
2088 
2089         // restore show state
2090         if ( mnShowState != mnFullScreenShowState )
2091         {
2092             mnShowState = mnFullScreenShowState;
2093             if ( bVisible )
2094             {
2095                 mbInShow = TRUE;
2096                 ShowWindow( mhWnd, mnShowState );
2097                 mbInShow = FALSE;
2098                 UpdateWindow( mhWnd );
2099             }
2100         }
2101     }
2102 }
2103 
2104 // -----------------------------------------------------------------------
2105 
2106 void WinSalFrame::StartPresentation( sal_Bool bStart )
2107 {
2108     if ( mbPresentation == bStart )
2109         return;
2110 
2111     mbPresentation = bStart;
2112 
2113     SalData* pSalData = GetSalData();
2114     if ( bStart )
2115     {
2116         if ( !pSalData->mpSageEnableProc )
2117         {
2118             if ( pSalData->mnSageStatus != DISABLE_AGENT )
2119             {
2120                 OFSTRUCT aOS;
2121                 OpenFile( "SAGE.DLL", &aOS, OF_EXIST );
2122 
2123                 if ( !aOS.nErrCode )
2124                 {
2125                     oslModule mhSageInst = osl_loadAsciiModule( aOS.szPathName, SAL_LOADMODULE_DEFAULT );
2126                     pSalData->mpSageEnableProc = (SysAgt_Enable_PROC)osl_getAsciiFunctionSymbol( mhSageInst, "System_Agent_Enable" );
2127                 }
2128                 else
2129                     pSalData->mnSageStatus = DISABLE_AGENT;
2130             }
2131         }
2132 
2133         if ( pSalData->mpSageEnableProc )
2134         {
2135             pSalData->mnSageStatus = pSalData->mpSageEnableProc( GET_AGENT_STATUS );
2136             if ( pSalData->mnSageStatus == ENABLE_AGENT )
2137                 pSalData->mpSageEnableProc( DISABLE_AGENT );
2138         }
2139 
2140         // Bildschirmschoner ausschalten, wenn Praesentation laueft
2141         SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0,
2142                               &(pSalData->mbScrSvrEnabled), 0 );
2143         if ( pSalData->mbScrSvrEnabled )
2144             SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, FALSE, 0, 0 );
2145     }
2146     else
2147     {
2148         // Bildschirmschoner wieder einschalten
2149         if ( pSalData->mbScrSvrEnabled )
2150             SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, pSalData->mbScrSvrEnabled, 0, 0 );
2151 
2152         // Systemagenten wieder aktivieren
2153         if ( pSalData->mnSageStatus == ENABLE_AGENT )
2154             pSalData->mpSageEnableProc( pSalData->mnSageStatus );
2155     }
2156 }
2157 
2158 // -----------------------------------------------------------------------
2159 
2160 void WinSalFrame::SetAlwaysOnTop( sal_Bool bOnTop )
2161 {
2162     HWND hWnd;
2163     if ( bOnTop )
2164         hWnd = HWND_TOPMOST;
2165     else
2166         hWnd = HWND_NOTOPMOST;
2167     SetWindowPos( mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
2168 }
2169 
2170 // -----------------------------------------------------------------------
2171 
2172 static void ImplSalToTop( HWND hWnd, sal_uInt16 nFlags )
2173 {
2174     WinSalFrame* pToTopFrame = GetWindowPtr( hWnd );
2175     if( pToTopFrame && (pToTopFrame->mnStyle & SAL_FRAME_STYLE_SYSTEMCHILD) != 0 )
2176         BringWindowToTop( hWnd );
2177 
2178     if ( nFlags & SAL_FRAME_TOTOP_FOREGROUNDTASK )
2179     {
2180         // This magic code is necessary to connect the input focus of the
2181         // current window thread and the thread which owns the window that
2182         // should be the new foreground window.
2183         HWND   hCurrWnd     = GetForegroundWindow();
2184         DWORD  myThreadID   = GetCurrentThreadId();
2185         DWORD  currThreadID = GetWindowThreadProcessId(hCurrWnd,NULL);
2186         AttachThreadInput(myThreadID, currThreadID,TRUE);
2187         SetForegroundWindow(hWnd);
2188         AttachThreadInput(myThreadID,currThreadID,FALSE);
2189     }
2190 
2191     if ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
2192     {
2193         HWND hIconicWnd = hWnd;
2194         while ( hIconicWnd )
2195         {
2196             if ( IsIconic( hIconicWnd ) )
2197             {
2198                 WinSalFrame* pFrame = GetWindowPtr( hIconicWnd );
2199                 if ( pFrame )
2200                 {
2201                     if ( GetWindowPtr( hWnd )->mbRestoreMaximize )
2202                         ShowWindow( hIconicWnd, SW_MAXIMIZE );
2203                     else
2204                         ShowWindow( hIconicWnd, SW_RESTORE );
2205                 }
2206                 else
2207                     ShowWindow( hIconicWnd, SW_RESTORE );
2208             }
2209 
2210             hIconicWnd = ::GetParent( hIconicWnd );
2211         }
2212     }
2213 
2214     if ( !IsIconic( hWnd ) && IsWindowVisible( hWnd ) )
2215     {
2216         SetFocus( hWnd );
2217 
2218         // Windows behauptet oefters mal, das man den Focus hat, obwohl
2219         // man diesen nicht hat. Wenn dies der Fall ist, dann versuchen
2220         // wir diesen auch ganz richtig zu bekommen.
2221         if ( ::GetFocus() == hWnd )
2222             SetForegroundWindow( hWnd );
2223     }
2224 }
2225 
2226 // -----------------------------------------------------------------------
2227 
2228 void WinSalFrame::ToTop( sal_uInt16 nFlags )
2229 {
2230 	nFlags &= ~SAL_FRAME_TOTOP_GRABFOCUS;	// this flag is not needed on win32
2231     // Post this Message to the window, because this only works
2232     // in the thread of the window, which has create this window.
2233     // We post this message to avoid deadlocks
2234     if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
2235         ImplPostMessage( mhWnd, SAL_MSG_TOTOP, nFlags, 0 );
2236     else
2237         ImplSalToTop( mhWnd, nFlags );
2238 }
2239 
2240 // -----------------------------------------------------------------------
2241 
2242 void WinSalFrame::SetPointer( PointerStyle ePointerStyle )
2243 {
2244     struct ImplPtrData
2245     {
2246         HCURSOR         mhCursor;
2247         LPCSTR          mnSysId;
2248         UINT            mnOwnId;
2249     };
2250 
2251     static ImplPtrData aImplPtrTab[POINTER_COUNT] =
2252     {
2253     { 0, IDC_ARROW, 0 },                            // POINTER_ARROW
2254     { 0, 0, SAL_RESID_POINTER_NULL },               // POINTER_NULL
2255     { 0, IDC_WAIT, 0 },                             // POINTER_WAIT
2256     { 0, IDC_IBEAM, 0 },                            // POINTER_TEXT
2257     { 0, IDC_HELP, 0 },                             // POINTER_HELP
2258     { 0, 0, SAL_RESID_POINTER_CROSS },              // POINTER_CROSS
2259     { 0, 0, SAL_RESID_POINTER_MOVE },               // POINTER_MOVE
2260     { 0, IDC_SIZENS, 0 },                           // POINTER_NSIZE
2261     { 0, IDC_SIZENS, 0 },                           // POINTER_SSIZE
2262     { 0, IDC_SIZEWE, 0 },                           // POINTER_WSIZE
2263     { 0, IDC_SIZEWE, 0 },                           // POINTER_ESIZE
2264     { 0, IDC_SIZENWSE, 0 },                         // POINTER_NWSIZE
2265     { 0, IDC_SIZENESW, 0 },                         // POINTER_NESIZE
2266     { 0, IDC_SIZENESW, 0 },                         // POINTER_SWSIZE
2267     { 0, IDC_SIZENWSE, 0 },                         // POINTER_SESIZE
2268     { 0, IDC_SIZENS, 0 },                           // POINTER_WINDOW_NSIZE
2269     { 0, IDC_SIZENS, 0 },                           // POINTER_WINDOW_SSIZE
2270     { 0, IDC_SIZEWE, 0 },                           // POINTER_WINDOW_WSIZE
2271     { 0, IDC_SIZEWE, 0 },                           // POINTER_WINDOW_ESIZE
2272     { 0, IDC_SIZENWSE, 0 },                         // POINTER_WINDOW_NWSIZE
2273     { 0, IDC_SIZENESW, 0 },                         // POINTER_WINDOW_NESIZE
2274     { 0, IDC_SIZENESW, 0 },                         // POINTER_WINDOW_SWSIZE
2275     { 0, IDC_SIZENWSE, 0 },                         // POINTER_WINDOW_SESIZE
2276     { 0, 0, SAL_RESID_POINTER_HSPLIT },             // POINTER_HSPLIT
2277     { 0, 0, SAL_RESID_POINTER_VSPLIT },             // POINTER_VSPLIT
2278     { 0, 0, SAL_RESID_POINTER_HSIZEBAR },           // POINTER_HSIZEBAR
2279     { 0, 0, SAL_RESID_POINTER_VSIZEBAR },           // POINTER_VSIZEBAR
2280     { 0, 0, SAL_RESID_POINTER_HAND },               // POINTER_HAND
2281     { 0, 0, SAL_RESID_POINTER_REFHAND },            // POINTER_REFHAND
2282     { 0, 0, SAL_RESID_POINTER_PEN },                // POINTER_PEN
2283     { 0, 0, SAL_RESID_POINTER_MAGNIFY },            // POINTER_MAGNIFY
2284     { 0, 0, SAL_RESID_POINTER_FILL },               // POINTER_FILL
2285     { 0, 0, SAL_RESID_POINTER_ROTATE },             // POINTER_ROTATE
2286     { 0, 0, SAL_RESID_POINTER_HSHEAR },             // POINTER_HSHEAR
2287     { 0, 0, SAL_RESID_POINTER_VSHEAR },             // POINTER_VSHEAR
2288     { 0, 0, SAL_RESID_POINTER_MIRROR },             // POINTER_MIRROR
2289     { 0, 0, SAL_RESID_POINTER_CROOK },              // POINTER_CROOK
2290     { 0, 0, SAL_RESID_POINTER_CROP },               // POINTER_CROP
2291     { 0, 0, SAL_RESID_POINTER_MOVEPOINT },          // POINTER_MOVEPOINT
2292     { 0, 0, SAL_RESID_POINTER_MOVEBEZIERWEIGHT },   // POINTER_MOVEBEZIERWEIGHT
2293     { 0, 0, SAL_RESID_POINTER_MOVEDATA },           // POINTER_MOVEDATA
2294     { 0, 0, SAL_RESID_POINTER_COPYDATA },           // POINTER_COPYDATA
2295     { 0, 0, SAL_RESID_POINTER_LINKDATA },           // POINTER_LINKDATA
2296     { 0, 0, SAL_RESID_POINTER_MOVEDATALINK },       // POINTER_MOVEDATALINK
2297     { 0, 0, SAL_RESID_POINTER_COPYDATALINK },       // POINTER_COPYDATALINK
2298     { 0, 0, SAL_RESID_POINTER_MOVEFILE },           // POINTER_MOVEFILE
2299     { 0, 0, SAL_RESID_POINTER_COPYFILE },           // POINTER_COPYFILE
2300     { 0, 0, SAL_RESID_POINTER_LINKFILE },           // POINTER_LINKFILE
2301     { 0, 0, SAL_RESID_POINTER_MOVEFILELINK },       // POINTER_MOVEFILELINK
2302     { 0, 0, SAL_RESID_POINTER_COPYFILELINK },       // POINTER_COPYFILELINK
2303     { 0, 0, SAL_RESID_POINTER_MOVEFILES },          // POINTER_MOVEFILES
2304     { 0, 0, SAL_RESID_POINTER_COPYFILES },          // POINTER_COPYFILES
2305     { 0, 0, SAL_RESID_POINTER_NOTALLOWED },         // POINTER_NOTALLOWED
2306     { 0, 0, SAL_RESID_POINTER_DRAW_LINE },          // POINTER_DRAW_LINE
2307     { 0, 0, SAL_RESID_POINTER_DRAW_RECT },          // POINTER_DRAW_RECT
2308     { 0, 0, SAL_RESID_POINTER_DRAW_POLYGON },       // POINTER_DRAW_POLYGON
2309     { 0, 0, SAL_RESID_POINTER_DRAW_BEZIER },        // POINTER_DRAW_BEZIER
2310     { 0, 0, SAL_RESID_POINTER_DRAW_ARC },           // POINTER_DRAW_ARC
2311     { 0, 0, SAL_RESID_POINTER_DRAW_PIE },           // POINTER_DRAW_PIE
2312     { 0, 0, SAL_RESID_POINTER_DRAW_CIRCLECUT },     // POINTER_DRAW_CIRCLECUT
2313     { 0, 0, SAL_RESID_POINTER_DRAW_ELLIPSE },       // POINTER_DRAW_ELLIPSE
2314     { 0, 0, SAL_RESID_POINTER_DRAW_FREEHAND },      // POINTER_DRAW_FREEHAND
2315     { 0, 0, SAL_RESID_POINTER_DRAW_CONNECT },       // POINTER_DRAW_CONNECT
2316     { 0, 0, SAL_RESID_POINTER_DRAW_TEXT },          // POINTER_DRAW_TEXT
2317     { 0, 0, SAL_RESID_POINTER_DRAW_CAPTION },       // POINTER_DRAW_CAPTION
2318     { 0, 0, SAL_RESID_POINTER_CHART },              // POINTER_CHART
2319     { 0, 0, SAL_RESID_POINTER_DETECTIVE },          // POINTER_DETECTIVE
2320     { 0, 0, SAL_RESID_POINTER_PIVOT_COL },          // POINTER_PIVOT_COL
2321     { 0, 0, SAL_RESID_POINTER_PIVOT_ROW },          // POINTER_PIVOT_ROW
2322     { 0, 0, SAL_RESID_POINTER_PIVOT_FIELD },        // POINTER_PIVOT_FIELD
2323     { 0, 0, SAL_RESID_POINTER_CHAIN },              // POINTER_CHAIN
2324     { 0, 0, SAL_RESID_POINTER_CHAIN_NOTALLOWED },   // POINTER_CHAIN_NOTALLOWED
2325     { 0, 0, SAL_RESID_POINTER_TIMEEVENT_MOVE },     // POINTER_TIMEEVENT_MOVE
2326     { 0, 0, SAL_RESID_POINTER_TIMEEVENT_SIZE },     // POINTER_TIMEEVENT_SIZE
2327     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_N },       // POINTER_AUTOSCROLL_N
2328     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_S },       // POINTER_AUTOSCROLL_S
2329     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_W },       // POINTER_AUTOSCROLL_W
2330     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_E },       // POINTER_AUTOSCROLL_E
2331     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NW },      // POINTER_AUTOSCROLL_NW
2332     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NE },      // POINTER_AUTOSCROLL_NE
2333     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SW },      // POINTER_AUTOSCROLL_SW
2334     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SE },      // POINTER_AUTOSCROLL_SE
2335     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NS },      // POINTER_AUTOSCROLL_NS
2336     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_WE },      // POINTER_AUTOSCROLL_WE
2337     { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NSWE },    // POINTER_AUTOSCROLL_NSWE
2338     { 0, 0, SAL_RESID_POINTER_AIRBRUSH },           // POINTER_AIRBRUSH
2339     { 0, 0, SAL_RESID_POINTER_TEXT_VERTICAL },      // POINTER_TEXT_VERTICAL
2340     { 0, 0, SAL_RESID_POINTER_PIVOT_DELETE },       // POINTER_PIVOT_DELETE
2341 
2342     // --> FME 2004-07-30 #i32329# Enhanced table selection
2343     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_S },       // POINTER_TAB_SELECT_S
2344     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_E },       // POINTER_TAB_SELECT_E
2345     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SE },      // POINTER_TAB_SELECT_SE
2346     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_W },       // POINTER_TAB_SELECT_W
2347     { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SW },      // POINTER_TAB_SELECT_SW
2348     // <--
2349 
2350     // --> FME 2004-08-16 #i20119# Paintbrush tool
2351     { 0, 0, SAL_RESID_POINTER_PAINTBRUSH }          // POINTER_PAINTBRUSH
2352     // <--
2353 
2354     };
2355 
2356 #if POINTER_COUNT != 94
2357 #error New Pointer must be defined!
2358 #endif
2359 
2360     // Mousepointer loaded ?
2361     if ( !aImplPtrTab[ePointerStyle].mhCursor )
2362     {
2363         if ( aImplPtrTab[ePointerStyle].mnOwnId )
2364             aImplPtrTab[ePointerStyle].mhCursor = ImplLoadSalCursor( aImplPtrTab[ePointerStyle].mnOwnId );
2365         else
2366             aImplPtrTab[ePointerStyle].mhCursor = LoadCursor( 0, aImplPtrTab[ePointerStyle].mnSysId );
2367     }
2368 
2369     // Unterscheidet sich der Mauspointer, dann den neuen setzen
2370     if ( mhCursor != aImplPtrTab[ePointerStyle].mhCursor )
2371     {
2372         mhCursor = aImplPtrTab[ePointerStyle].mhCursor;
2373         SetCursor( mhCursor );
2374     }
2375 }
2376 
2377 // -----------------------------------------------------------------------
2378 
2379 void WinSalFrame::CaptureMouse( sal_Bool bCapture )
2380 {
2381     // Send this Message to the window, because CaptureMouse() only work
2382     // in the thread of the window, which has create this window
2383     int nMsg;
2384     if ( bCapture )
2385         nMsg = SAL_MSG_CAPTUREMOUSE;
2386     else
2387         nMsg = SAL_MSG_RELEASEMOUSE;
2388     ImplSendMessage( mhWnd, nMsg, 0, 0 );
2389 }
2390 
2391 // -----------------------------------------------------------------------
2392 
2393 void WinSalFrame::SetPointerPos( long nX, long nY )
2394 {
2395     POINT aPt;
2396     aPt.x = (int)nX;
2397     aPt.y = (int)nY;
2398     ClientToScreen( mhWnd, &aPt );
2399     SetCursorPos( aPt.x, aPt.y );
2400 }
2401 
2402 // -----------------------------------------------------------------------
2403 
2404 void WinSalFrame::Flush()
2405 {
2406     GdiFlush();
2407 }
2408 
2409 // -----------------------------------------------------------------------
2410 
2411 void WinSalFrame::Sync()
2412 {
2413     GdiFlush();
2414 }
2415 
2416 // -----------------------------------------------------------------------
2417 
2418 static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pContext )
2419 {
2420     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
2421     sal_Bool        bIME = (pContext->mnOptions & SAL_INPUTCONTEXT_TEXT) != 0;
2422     if ( bIME )
2423     {
2424         if ( !pFrame->mbIME )
2425         {
2426             pFrame->mbIME = TRUE;
2427 
2428             if ( pFrame->mhDefIMEContext )
2429             {
2430                 ImmAssociateContext( pFrame->mhWnd, pFrame->mhDefIMEContext );
2431                 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
2432                 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
2433                 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
2434                 pFrame->mbHandleIME = !pFrame->mbSpezIME;
2435             }
2436         }
2437 
2438         // When the application can't handle IME messages, then the
2439         // System should handle the IME handling
2440         if ( !(pContext->mnOptions & SAL_INPUTCONTEXT_EXTTEXTINPUT) )
2441             pFrame->mbHandleIME = FALSE;
2442 
2443         // Set the Font for IME Handling
2444         if ( pContext->mpFont )
2445         {
2446             HIMC hIMC = ImmGetContext( pFrame->mhWnd );
2447             if ( hIMC )
2448             {
2449                 LOGFONTW aLogFont;
2450                 HDC hDC = GetDC( pFrame->mhWnd );
2451                 // In case of vertical writing, always append a '@' to the
2452                 // Windows font name, not only if such a Windows font really is
2453                 // available (bTestVerticalAvail == false in the below call):
2454                 // The Windows IME's candidates window seems to always use a
2455                 // font that has all necessary glyphs, not necessarily the one
2456                 // specified by this font name; but it seems to decide whether
2457                 // to use that font's horizontal or vertical variant based on a
2458                 // '@' in front of this font name.
2459                 ImplGetLogFontFromFontSelect( hDC, pContext->mpFont, aLogFont,
2460                                               false );
2461                 ReleaseDC( pFrame->mhWnd, hDC );
2462                 ImmSetCompositionFontW( hIMC, &aLogFont );
2463                 ImmReleaseContext( pFrame->mhWnd, hIMC );
2464             }
2465         }
2466     }
2467     else
2468     {
2469         if ( pFrame->mbIME )
2470         {
2471             pFrame->mbIME = FALSE;
2472             pFrame->mbHandleIME = FALSE;
2473             ImmAssociateContext( pFrame->mhWnd, 0 );
2474         }
2475     }
2476 }
2477 
2478 // -----------------------------------------------------------------------
2479 
2480 void WinSalFrame::SetInputContext( SalInputContext* pContext )
2481 {
2482     // Must be called in the main thread!
2483     ImplSendMessage( mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, (LPARAM)(void*)pContext );
2484 }
2485 
2486 // -----------------------------------------------------------------------
2487 
2488 static void ImplSalFrameEndExtTextInput( HWND hWnd, sal_uInt16 nFlags )
2489 {
2490     HIMC hIMC = ImmGetContext( hWnd );
2491     if ( hIMC )
2492     {
2493         DWORD nIndex;
2494         if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE )
2495             nIndex = CPS_COMPLETE;
2496         else
2497             nIndex = CPS_CANCEL;
2498 
2499         ImmNotifyIME( hIMC, NI_COMPOSITIONSTR, nIndex, 0 );
2500         ImmReleaseContext( hWnd, hIMC );
2501     }
2502 }
2503 
2504 // -----------------------------------------------------------------------
2505 
2506 void WinSalFrame::EndExtTextInput( sal_uInt16 nFlags )
2507 {
2508     // Must be called in the main thread!
2509     ImplSendMessage( mhWnd, SAL_MSG_ENDEXTTEXTINPUT, (WPARAM)nFlags, 0 );
2510 }
2511 
2512 // -----------------------------------------------------------------------
2513 
2514 static void ImplGetKeyNameText( LONG lParam, sal_Unicode* pBuf,
2515                                 UINT& rCount, UINT nMaxSize,
2516                                 const sal_Char* pReplace )
2517 {
2518     DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::ImplGetKeyNameTextW(): WCHAR != sal_Unicode" );
2519 
2520     static const int nMaxKeyLen = 350;
2521     WCHAR aKeyBuf[ nMaxKeyLen ];
2522     int nKeyLen = 0;
2523     if ( lParam )
2524     {
2525         if ( true/*aSalShlData.mbWNT*/ )
2526         {
2527             nKeyLen = GetKeyNameTextW( lParam, aKeyBuf, nMaxKeyLen );
2528             DBG_ASSERT( nKeyLen <= nMaxKeyLen, "Invalid key name length!" );
2529             if( nKeyLen > nMaxKeyLen )
2530                 nKeyLen = 0;
2531             else if( nKeyLen > 0 )
2532             {
2533                 // Capitalize just the first letter of key names
2534                 CharLowerBuffW( aKeyBuf, nKeyLen );
2535 
2536                 bool bUpper = true;
2537                 for( WCHAR *pW=aKeyBuf, *pE=pW+nKeyLen; pW < pE; ++pW )
2538                 {
2539                     if( bUpper )
2540                         CharUpperBuffW( pW, 1 );
2541                     bUpper = (*pW=='+') || (*pW=='-') || (*pW==' ') || (*pW=='.');
2542                 }
2543             }
2544         }
2545     }
2546 
2547     if ( (nKeyLen > 0) || pReplace )
2548     {
2549         if( (rCount > 0) && (rCount < nMaxSize) )
2550         {
2551             pBuf[rCount] = '+';
2552             rCount++;
2553         }
2554 
2555         if( nKeyLen > 0 )
2556         {
2557             if( nKeyLen + rCount > nMaxSize )
2558                 nKeyLen = nMaxSize - rCount;
2559             memcpy( pBuf+rCount, aKeyBuf, nKeyLen*sizeof( sal_Unicode ) );
2560             rCount += nKeyLen;
2561         }
2562         else // fall back to provided default name
2563         {
2564             while( *pReplace && (rCount < nMaxSize) )
2565             {
2566                 pBuf[rCount] = *pReplace;
2567                 rCount++;
2568                 pReplace++;
2569             }
2570         }
2571     }
2572     else
2573         rCount = 0;
2574 }
2575 
2576 // -----------------------------------------------------------------------
2577 
2578 XubString WinSalFrame::GetKeyName( sal_uInt16 nKeyCode )
2579 {
2580     static const int nMaxKeyLen = 350;
2581     sal_Unicode aKeyBuf[ nMaxKeyLen ];
2582     UINT        nKeyBufLen = 0;
2583     UINT        nSysCode = 0;
2584 
2585     if ( nKeyCode & KEY_MOD1 )
2586     {
2587         nSysCode = MapVirtualKey( VK_CONTROL, 0 );
2588         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2589         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Ctrl" );
2590     }
2591 
2592     if ( nKeyCode & KEY_MOD2 )
2593     {
2594         nSysCode = MapVirtualKey( VK_MENU, 0 );
2595         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2596         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Alt" );
2597     }
2598 
2599     if ( nKeyCode & KEY_SHIFT )
2600     {
2601         nSysCode = MapVirtualKey( VK_SHIFT, 0 );
2602         nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25);
2603         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Shift" );
2604     }
2605 
2606     sal_uInt16      nCode = nKeyCode & 0x0FFF;
2607     sal_uLong       nSysCode2 = 0;
2608     sal_Char*   pReplace = NULL;
2609     sal_Unicode cSVCode = 0;
2610     sal_Char    aFBuf[4];
2611     nSysCode = 0;
2612 
2613     if ( (nCode >= KEY_0) && (nCode <= KEY_9) )
2614         cSVCode = '0' + (nCode - KEY_0);
2615     else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) )
2616         cSVCode = 'A' + (nCode - KEY_A);
2617     else if ( (nCode >= KEY_F1) && (nCode <= KEY_F26) )
2618     {
2619         nSysCode = VK_F1 + (nCode - KEY_F1);
2620         aFBuf[0] = 'F';
2621         if ( (nCode >= KEY_F1) && (nCode <= KEY_F9) )
2622         {
2623             aFBuf[1] = sal::static_int_cast<sal_Char>('1' + (nCode - KEY_F1));
2624             aFBuf[2] = 0;
2625         }
2626         else if ( (nCode >= KEY_F10) && (nCode <= KEY_F19) )
2627         {
2628             aFBuf[1] = '1';
2629             aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F10));
2630             aFBuf[3] = 0;
2631         }
2632         else
2633         {
2634             aFBuf[1] = '2';
2635             aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F20));
2636             aFBuf[3] = 0;
2637         }
2638         pReplace = aFBuf;
2639     }
2640     else
2641     {
2642         switch ( nCode )
2643         {
2644             case KEY_DOWN:
2645                 nSysCode = VK_DOWN;
2646                 nSysCode2 = (((sal_uLong)1) << 24);
2647                 pReplace = "Down";
2648                 break;
2649             case KEY_UP:
2650                 nSysCode = VK_UP;
2651                 nSysCode2 = (((sal_uLong)1) << 24);
2652                 pReplace = "Up";
2653                 break;
2654             case KEY_LEFT:
2655                 nSysCode = VK_LEFT;
2656                 nSysCode2 = (((sal_uLong)1) << 24);
2657                 pReplace = "Left";
2658                 break;
2659             case KEY_RIGHT:
2660                 nSysCode = VK_RIGHT;
2661                 nSysCode2 = (((sal_uLong)1) << 24);
2662                 pReplace = "Right";
2663                 break;
2664             case KEY_HOME:
2665                 nSysCode = VK_HOME;
2666                 nSysCode2 = (((sal_uLong)1) << 24);
2667                 pReplace = "Home";
2668                 break;
2669             case KEY_END:
2670                 nSysCode = VK_END;
2671                 nSysCode2 = (((sal_uLong)1) << 24);
2672                 pReplace = "End";
2673                 break;
2674             case KEY_PAGEUP:
2675                 nSysCode = VK_PRIOR;
2676                 nSysCode2 = (((sal_uLong)1) << 24);
2677                 pReplace = "Page Up";
2678                 break;
2679             case KEY_PAGEDOWN:
2680                 nSysCode = VK_NEXT;
2681                 nSysCode2 = (((sal_uLong)1) << 24);
2682                 pReplace = "Page Down";
2683                 break;
2684             case KEY_RETURN:
2685                 nSysCode = VK_RETURN;
2686                 pReplace = "Enter";
2687                 break;
2688             case KEY_ESCAPE:
2689                 nSysCode = VK_ESCAPE;
2690                 pReplace = "Escape";
2691                 break;
2692             case KEY_TAB:
2693                 nSysCode = VK_TAB;
2694                 pReplace = "Tab";
2695                 break;
2696             case KEY_BACKSPACE:
2697                 nSysCode = VK_BACK;
2698                 pReplace = "Backspace";
2699                 break;
2700             case KEY_SPACE:
2701                 nSysCode = VK_SPACE;
2702                 pReplace = "Space";
2703                 break;
2704             case KEY_INSERT:
2705                 nSysCode = VK_INSERT;
2706                 nSysCode2 = (((sal_uLong)1) << 24);
2707                 pReplace = "Insert";
2708                 break;
2709             case KEY_DELETE:
2710                 nSysCode = VK_DELETE;
2711                 nSysCode2 = (((sal_uLong)1) << 24);
2712                 pReplace = "Delete";
2713                 break;
2714 
2715             case KEY_ADD:
2716                 cSVCode  = '+';
2717                 break;
2718             case KEY_SUBTRACT:
2719                 cSVCode  = '-';
2720                 break;
2721             case KEY_MULTIPLY:
2722                 cSVCode  = '*';
2723                 break;
2724             case KEY_DIVIDE:
2725                 cSVCode  = '/';
2726                 break;
2727             case KEY_POINT:
2728                 cSVCode  = '.';
2729                 break;
2730             case KEY_COMMA:
2731                 cSVCode  = ',';
2732                 break;
2733             case KEY_LESS:
2734                 cSVCode  = '<';
2735                 break;
2736             case KEY_GREATER:
2737                 cSVCode  = '>';
2738                 break;
2739             case KEY_EQUAL:
2740                 cSVCode  = '=';
2741                 break;
2742         }
2743     }
2744 
2745     if ( nSysCode )
2746     {
2747         nSysCode = MapVirtualKey( (UINT)nSysCode, 0 );
2748         if ( nSysCode )
2749             nSysCode = (nSysCode << 16) | nSysCode2;
2750         ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, pReplace );
2751     }
2752     else
2753     {
2754         if ( cSVCode )
2755         {
2756             if ( nKeyBufLen > 0 )
2757                 aKeyBuf[ nKeyBufLen++ ] = '+';
2758             if( nKeyBufLen < nMaxKeyLen )
2759                 aKeyBuf[ nKeyBufLen++ ] = cSVCode;
2760         }
2761     }
2762 
2763     if( !nKeyBufLen )
2764         return XubString();
2765 
2766     return XubString( aKeyBuf, sal::static_int_cast< sal_uInt16 >(nKeyBufLen) );
2767 }
2768 
2769 // -----------------------------------------------------------------------
2770 
2771 XubString WinSalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode )
2772 {
2773     return GetKeyName( nKeyCode );
2774 }
2775 
2776 // -----------------------------------------------------------------------
2777 
2778 inline Color ImplWinColorToSal( COLORREF nColor )
2779 {
2780     return Color( GetRValue( nColor ), GetGValue( nColor ), GetBValue( nColor ) );
2781 }
2782 
2783 // -----------------------------------------------------------------------
2784 
2785 static void ImplSalUpdateStyleFontA( HDC hDC, const LOGFONTA& rLogFont, Font& rFont )
2786 {
2787     ImplSalLogFontToFontA( hDC, rLogFont, rFont );
2788 
2789     // On Windows 9x, Windows NT we get sometimes very small sizes
2790     // (for example for the small Caption height).
2791     // So if it is MS Sans Serif, a none scalable font we use
2792     // 8 Point as the minimum control height, in all other cases
2793     // 6 Point is the smallest one
2794     if ( rFont.GetHeight() < 8 )
2795     {
2796         if ( rtl_str_compareIgnoreAsciiCase( rLogFont.lfFaceName, "MS Sans Serif" ) == 0 )
2797             rFont.SetHeight( 8 );
2798         else if ( rFont.GetHeight() < 6 )
2799             rFont.SetHeight( 6 );
2800     }
2801 }
2802 
2803 // -----------------------------------------------------------------------
2804 
2805 static void ImplSalUpdateStyleFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont )
2806 {
2807     ImplSalLogFontToFontW( hDC, rLogFont, rFont );
2808 
2809     // On Windows 9x, Windows NT we get sometimes very small sizes
2810     // (for example for the small Caption height).
2811     // So if it is MS Sans Serif, a none scalable font we use
2812     // 8 Point as the minimum control height, in all other cases
2813     // 6 Point is the smallest one
2814     if ( rFont.GetHeight() < 8 )
2815     {
2816         if ( rtl_ustr_compareIgnoreAsciiCase( reinterpret_cast<const sal_Unicode*>(rLogFont.lfFaceName), reinterpret_cast<const sal_Unicode*>(L"MS Sans Serif") ) == 0 )
2817             rFont.SetHeight( 8 );
2818         else if ( rFont.GetHeight() < 6 )
2819             rFont.SetHeight( 6 );
2820     }
2821 }
2822 
2823 // -----------------------------------------------------------------------
2824 
2825 static long ImplA2I( const BYTE* pStr )
2826 {
2827     long    n = 0;
2828     int     nSign = 1;
2829 
2830     if ( *pStr == '-' )
2831     {
2832         nSign = -1;
2833         pStr++;
2834     }
2835 
2836     while( (*pStr >= 48) && (*pStr <= 57) )
2837     {
2838         n *= 10;
2839         n += ((*pStr) - 48);
2840         pStr++;
2841     }
2842 
2843     n *= nSign;
2844 
2845     return n;
2846 }
2847 
2848 // -----------------------------------------------------------------------
2849 static HRESULT WINAPI backwardCompatibleDwmIsCompositionEnabled( BOOL* pOut )
2850 {
2851     *pOut = FALSE;
2852     return S_OK;
2853 }
2854 
2855 static BOOL ImplDwmIsCompositionEnabled()
2856 {
2857     SalData* pSalData = GetSalData();
2858     if( ! pSalData->mpDwmIsCompositionEnabled )
2859     {
2860         pSalData->maDwmLib = osl_loadAsciiModule( "Dwmapi.dll", SAL_LOADMODULE_DEFAULT );
2861         if( pSalData->maDwmLib )
2862             pSalData->mpDwmIsCompositionEnabled = (DwmIsCompositionEnabled_ptr)osl_getAsciiFunctionSymbol( pSalData->maDwmLib, "DwmIsCompositionEnabled" );
2863         if( ! pSalData->mpDwmIsCompositionEnabled ) // something failed
2864             pSalData->mpDwmIsCompositionEnabled = backwardCompatibleDwmIsCompositionEnabled;
2865     }
2866     BOOL aResult = FALSE;
2867     HRESULT nError = pSalData->mpDwmIsCompositionEnabled( &aResult );
2868     return nError == S_OK && aResult;
2869 }
2870 
2871 
2872 void WinSalFrame::UpdateSettings( AllSettings& rSettings )
2873 {
2874     MouseSettings aMouseSettings = rSettings.GetMouseSettings();
2875     aMouseSettings.SetDoubleClickTime( GetDoubleClickTime() );
2876     aMouseSettings.SetDoubleClickWidth( GetSystemMetrics( SM_CXDOUBLECLK ) );
2877     aMouseSettings.SetDoubleClickHeight( GetSystemMetrics( SM_CYDOUBLECLK ) );
2878     long nDragWidth = GetSystemMetrics( SM_CXDRAG );
2879     long nDragHeight = GetSystemMetrics( SM_CYDRAG );
2880     if ( nDragWidth )
2881         aMouseSettings.SetStartDragWidth( nDragWidth );
2882     if ( nDragHeight )
2883         aMouseSettings.SetStartDragHeight( nDragHeight );
2884     HKEY hRegKey;
2885     if ( RegOpenKey( HKEY_CURRENT_USER,
2886                      "Control Panel\\Desktop",
2887                      &hRegKey ) == ERROR_SUCCESS )
2888     {
2889         BYTE    aValueBuf[10];
2890         DWORD   nValueSize = sizeof( aValueBuf );
2891         DWORD   nType;
2892         if ( RegQueryValueEx( hRegKey, "MenuShowDelay", 0,
2893                               &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
2894         {
2895             if ( nType == REG_SZ )
2896                 aMouseSettings.SetMenuDelay( (sal_uLong)ImplA2I( aValueBuf ) );
2897         }
2898 
2899         RegCloseKey( hRegKey );
2900     }
2901 
2902     StyleSettings aStyleSettings = rSettings.GetStyleSettings();
2903     // TODO: once those options vanish: just set bCompBorder to TRUE
2904     // to have the system colors read
2905     aStyleSettings.SetScrollBarSize( GetSystemMetrics( SM_CXVSCROLL ) );
2906     aStyleSettings.SetSpinSize( GetSystemMetrics( SM_CXVSCROLL ) );
2907     aStyleSettings.SetCursorBlinkTime( GetCaretBlinkTime() );
2908     aStyleSettings.SetFloatTitleHeight( GetSystemMetrics( SM_CYSMCAPTION ) );
2909     aStyleSettings.SetTitleHeight( GetSystemMetrics( SM_CYCAPTION ) );
2910     aStyleSettings.SetActiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVEBORDER ) ) );
2911     aStyleSettings.SetDeactiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVEBORDER ) ) );
2912     if ( aSalShlData.mnVersion >= 410 )
2913     {
2914         aStyleSettings.SetActiveColor2( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTACTIVECAPTION ) ) );
2915         aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTINACTIVECAPTION ) ) );
2916     }
2917     aStyleSettings.SetFaceColor( ImplWinColorToSal( GetSysColor( COLOR_3DFACE ) ) );
2918     aStyleSettings.SetInactiveTabColor( aStyleSettings.GetFaceColor() );
2919     aStyleSettings.SetLightColor( ImplWinColorToSal( GetSysColor( COLOR_3DHILIGHT ) ) );
2920     aStyleSettings.SetLightBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DLIGHT ) ) );
2921     aStyleSettings.SetShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
2922     aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DDKSHADOW ) ) );
2923     aStyleSettings.SetWorkspaceColor( ImplWinColorToSal( GetSysColor( COLOR_APPWORKSPACE ) ) );
2924     aStyleSettings.SetHelpColor( ImplWinColorToSal( GetSysColor( COLOR_INFOBK ) ) );
2925     aStyleSettings.SetHelpTextColor( ImplWinColorToSal( GetSysColor( COLOR_INFOTEXT ) ) );
2926     aStyleSettings.SetDialogColor( aStyleSettings.GetFaceColor() );
2927     aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() );
2928     aStyleSettings.SetButtonTextColor( ImplWinColorToSal( GetSysColor( COLOR_BTNTEXT ) ) );
2929     aStyleSettings.SetButtonRolloverTextColor( aStyleSettings.GetButtonTextColor() );
2930     aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
2931     aStyleSettings.SetGroupTextColor( aStyleSettings.GetRadioCheckTextColor() );
2932     aStyleSettings.SetLabelTextColor( aStyleSettings.GetRadioCheckTextColor() );
2933     aStyleSettings.SetInfoTextColor( aStyleSettings.GetRadioCheckTextColor() );
2934     aStyleSettings.SetWindowColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOW ) ) );
2935     aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() );
2936     aStyleSettings.SetWindowTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) );
2937     aStyleSettings.SetFieldColor( aStyleSettings.GetWindowColor() );
2938     aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() );
2939     aStyleSettings.SetFieldRolloverTextColor( aStyleSettings.GetFieldTextColor() );
2940     aStyleSettings.SetHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHT ) ) );
2941     aStyleSettings.SetHighlightTextColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHTTEXT ) ) );
2942     aStyleSettings.SetMenuHighlightColor( aStyleSettings.GetHighlightColor() );
2943     aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetHighlightTextColor() );
2944 
2945     ImplSVData* pSVData = ImplGetSVData();
2946     pSVData->maNWFData.mnMenuFormatExtraBorder = 0;
2947     pSVData->maNWFData.maMenuBarHighlightTextColor = Color( COL_TRANSPARENT );
2948     GetSalData()->mbThemeMenuSupport = FALSE;
2949     aStyleSettings.SetMenuColor( ImplWinColorToSal( GetSysColor( COLOR_MENU ) ) );
2950     aStyleSettings.SetMenuBarColor( aStyleSettings.GetMenuColor() );
2951     aStyleSettings.SetMenuBorderColor( aStyleSettings.GetLightBorderColor() ); // overriden below for flat menus
2952     aStyleSettings.SetUseFlatBorders( FALSE );
2953     aStyleSettings.SetUseFlatMenues( FALSE );
2954     aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
2955     aStyleSettings.SetMenuBarTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) );
2956     aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) );
2957     aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) );
2958     aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) );
2959     aStyleSettings.SetDeactiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ) );
2960     if ( aSalShlData.mbWXP )
2961     {
2962         // only xp supports a different menu bar color
2963         long bFlatMenues = 0;
2964         SystemParametersInfo( SPI_GETFLATMENU, 0, &bFlatMenues, 0);
2965         if( bFlatMenues )
2966         {
2967             aStyleSettings.SetUseFlatMenues( TRUE );
2968             aStyleSettings.SetMenuBarColor( ImplWinColorToSal( GetSysColor( COLOR_MENUBAR ) ) );
2969             aStyleSettings.SetMenuHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_MENUHILIGHT ) ) );
2970             aStyleSettings.SetMenuBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) );
2971 
2972             // flat borders for our controls etc. as well in this mode (ie, no 3d borders)
2973             // this is not active in the classic style appearance
2974             aStyleSettings.SetUseFlatBorders( TRUE );
2975         }
2976     }
2977     // check if vista or newer runs
2978     // in Aero theme (and similar ?) the menu text color does not change
2979     // for selected items; also on WinXP and earlier menus are not themed
2980     if( aSalShlData.maVersionInfo.dwMajorVersion >= 6 &&
2981        ImplDwmIsCompositionEnabled()
2982        )
2983     {
2984         // in aero menuitem highlight text is drawn in the same color as normal
2985         aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetMenuTextColor() );
2986         pSVData->maNWFData.mnMenuFormatExtraBorder = 2;
2987         pSVData->maNWFData.maMenuBarHighlightTextColor = aStyleSettings.GetMenuTextColor();
2988         GetSalData()->mbThemeMenuSupport = TRUE;
2989     }
2990     // Bei hellgrau geben wir die Farbe vor, damit es besser aussieht
2991     if ( aStyleSettings.GetFaceColor() == COL_LIGHTGRAY )
2992         aStyleSettings.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
2993     else
2994     {
2995         // Checked-Color berechnen
2996         Color   aColor1 = aStyleSettings.GetFaceColor();
2997         Color   aColor2 = aStyleSettings.GetLightColor();
2998         BYTE    nRed    = (BYTE)(((sal_uInt16)aColor1.GetRed()   + (sal_uInt16)aColor2.GetRed())/2);
2999         BYTE    nGreen  = (BYTE)(((sal_uInt16)aColor1.GetGreen() + (sal_uInt16)aColor2.GetGreen())/2);
3000         BYTE    nBlue   = (BYTE)(((sal_uInt16)aColor1.GetBlue()  + (sal_uInt16)aColor2.GetBlue())/2);
3001         aStyleSettings.SetCheckedColor( Color( nRed, nGreen, nBlue ) );
3002     }
3003 
3004     // caret width
3005     DWORD nCaretWidth = 2;
3006     if( SystemParametersInfo( SPI_GETCARETWIDTH, 0, &nCaretWidth, 0 ) )
3007         aStyleSettings.SetCursorSize( nCaretWidth );
3008 
3009 	// High contrast
3010 	HIGHCONTRAST hc;
3011 	hc.cbSize = sizeof( HIGHCONTRAST );
3012 	if( SystemParametersInfo( SPI_GETHIGHCONTRAST, hc.cbSize, &hc, 0) && (hc.dwFlags & HCF_HIGHCONTRASTON) )
3013 		aStyleSettings.SetHighContrastMode( 1 );
3014 	else
3015 		aStyleSettings.SetHighContrastMode( 0 );
3016 
3017 
3018     // Query Fonts
3019     Font    aMenuFont = aStyleSettings.GetMenuFont();
3020     Font    aTitleFont = aStyleSettings.GetTitleFont();
3021     Font    aFloatTitleFont = aStyleSettings.GetFloatTitleFont();
3022     Font    aHelpFont = aStyleSettings.GetHelpFont();
3023     Font    aAppFont = aStyleSettings.GetAppFont();
3024     Font    aIconFont = aStyleSettings.GetIconFont();
3025     HDC     hDC = GetDC( 0 );
3026     if( true/*aSalShlData.mbWNT*/ )
3027     {
3028         NONCLIENTMETRICSW aNonClientMetrics;
3029         aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
3030         if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
3031         {
3032             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMenuFont, aMenuFont );
3033             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont );
3034             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont );
3035             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfStatusFont, aHelpFont );
3036             ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMessageFont, aAppFont );
3037 
3038             LOGFONTW aLogFont;
3039             if ( SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) )
3040                 ImplSalUpdateStyleFontW( hDC, aLogFont, aIconFont );
3041         }
3042     }
3043 
3044     // get screen font resolution to calculate toolbox item size
3045 	long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY );
3046 
3047     ReleaseDC( 0, hDC );
3048 
3049     long nHeightPx = aMenuFont.GetHeight() * nDPIY / 72;
3050     aStyleSettings.SetToolbarIconSize( (((nHeightPx-1)*2) >= 28) ? STYLE_TOOLBAR_ICONSIZE_LARGE : STYLE_TOOLBAR_ICONSIZE_SMALL );
3051 
3052     aStyleSettings.SetMenuFont( aMenuFont );
3053     aStyleSettings.SetTitleFont( aTitleFont );
3054     aStyleSettings.SetFloatTitleFont( aFloatTitleFont );
3055     aStyleSettings.SetHelpFont( aHelpFont );
3056     aStyleSettings.SetIconFont( aIconFont );
3057     // We prefer Arial in the russian version, because MS Sans Serif
3058     // is to wide for the dialogs
3059     if ( rSettings.GetLanguage() == LANGUAGE_RUSSIAN )
3060     {
3061         XubString aFontName = aAppFont.GetName();
3062         XubString aFirstName = aFontName.GetToken( 0, ';' );
3063         if ( aFirstName.EqualsIgnoreCaseAscii( "MS Sans Serif" ) )
3064         {
3065             aFontName.InsertAscii( "Arial;", 0 );
3066             aAppFont.SetName( aFontName );
3067         }
3068     }
3069     aStyleSettings.SetAppFont( aAppFont );
3070     aStyleSettings.SetGroupFont( aAppFont );
3071     aStyleSettings.SetLabelFont( aAppFont );
3072     aStyleSettings.SetRadioCheckFont( aAppFont );
3073     aStyleSettings.SetPushButtonFont( aAppFont );
3074     aStyleSettings.SetFieldFont( aAppFont );
3075     if ( aAppFont.GetWeight() > WEIGHT_NORMAL )
3076         aAppFont.SetWeight( WEIGHT_NORMAL );
3077     aStyleSettings.SetInfoFont( aAppFont );
3078     aStyleSettings.SetToolFont( aAppFont );
3079 
3080     BOOL bDragFull;
3081     if ( SystemParametersInfo( SPI_GETDRAGFULLWINDOWS, 0, &bDragFull, 0 ) )
3082     {
3083         sal_uLong nDragFullOptions = aStyleSettings.GetDragFullOptions();
3084         if ( bDragFull )
3085             nDragFullOptions |=  DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT;
3086         else
3087             nDragFullOptions &= ~(DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT);
3088         aStyleSettings.SetDragFullOptions( nDragFullOptions );
3089     }
3090 
3091     aStyleSettings.SetIconHorzSpace( GetSystemMetrics( SM_CXICONSPACING ) );
3092     aStyleSettings.SetIconVertSpace( GetSystemMetrics( SM_CYICONSPACING ) );
3093     if ( RegOpenKey( HKEY_CURRENT_USER,
3094                      "Control Panel\\International\\Calendars\\TwoDigitYearMax",
3095                      &hRegKey ) == ERROR_SUCCESS )
3096     {
3097         BYTE    aValueBuf[10];
3098         DWORD   nValue;
3099         DWORD   nValueSize = sizeof( aValueBuf );
3100         DWORD   nType;
3101         if ( RegQueryValueEx( hRegKey, "1", 0,
3102                               &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS )
3103         {
3104             if ( nType == REG_SZ )
3105             {
3106                 nValue = (sal_uLong)ImplA2I( aValueBuf );
3107                 if ( (nValue > 1000) && (nValue < 10000) )
3108                 {
3109                     MiscSettings aMiscSettings = rSettings.GetMiscSettings();
3110 					utl::MiscCfg().SetYear2000( (sal_Int32)(nValue-99) );
3111                     rSettings.SetMiscSettings( aMiscSettings );
3112                 }
3113             }
3114         }
3115 
3116         RegCloseKey( hRegKey );
3117     }
3118 
3119     rSettings.SetMouseSettings( aMouseSettings );
3120     rSettings.SetStyleSettings( aStyleSettings );
3121 }
3122 
3123 // -----------------------------------------------------------------------
3124 
3125 SalBitmap* WinSalFrame::SnapShot()
3126 {
3127     WinSalBitmap* pSalBitmap = NULL;
3128 
3129     RECT aRect;
3130     GetWindowRect( mhWnd, &aRect );
3131 
3132     int     nDX = aRect.right-aRect.left;
3133     int     nDY = aRect.bottom-aRect.top;
3134     HDC     hDC = GetWindowDC( mhWnd );
3135     HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY );
3136     HDC     hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap );
3137     sal_Bool    bRet;
3138 
3139     bRet = BitBlt( hBmpDC, 0, 0, nDX, nDY, hDC, 0, 0, SRCCOPY ) ? TRUE : FALSE;
3140     ImplReleaseCachedDC( CACHED_HDC_1 );
3141 
3142     if ( bRet )
3143     {
3144         pSalBitmap = new WinSalBitmap;
3145 
3146         if ( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) )
3147         {
3148             delete pSalBitmap;
3149             pSalBitmap = NULL;
3150         }
3151     }
3152 
3153     return pSalBitmap;
3154 }
3155 
3156 // -----------------------------------------------------------------------
3157 
3158 const SystemEnvData* WinSalFrame::GetSystemData() const
3159 {
3160     return &maSysData;
3161 }
3162 
3163 // -----------------------------------------------------------------------
3164 
3165 void WinSalFrame::Beep( SoundType eSoundType )
3166 {
3167     static UINT aImplSoundTab[5] =
3168     {
3169         0,                              // SOUND_DEFAULT
3170         MB_ICONASTERISK,                // SOUND_INFO
3171         MB_ICONEXCLAMATION,             // SOUND_WARNING
3172         MB_ICONHAND,                    // SOUND_ERROR
3173         MB_ICONQUESTION                 // SOUND_QUERY
3174     };
3175 
3176     if( eSoundType != SOUND_DISABLE ) // don't beep on disable
3177         MessageBeep( aImplSoundTab[eSoundType] );
3178 }
3179 
3180 // -----------------------------------------------------------------------
3181 
3182 SalFrame::SalPointerState WinSalFrame::GetPointerState()
3183 {
3184     SalPointerState aState;
3185     aState.mnState = 0;
3186 
3187     if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
3188         aState.mnState |= MOUSE_LEFT;
3189     if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
3190         aState.mnState |= MOUSE_MIDDLE;
3191     if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
3192         aState.mnState |= MOUSE_RIGHT;
3193     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3194         aState.mnState |= KEY_SHIFT;
3195     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3196         aState.mnState |= KEY_MOD1;
3197     if ( GetKeyState( VK_MENU ) & 0x8000 )
3198         aState.mnState |= KEY_MOD2;
3199 
3200     POINT pt;
3201     GetCursorPos( &pt );
3202 
3203     aState.maPos = Point( pt.x - maGeometry.nX, pt.y - maGeometry.nY );
3204     return aState;
3205 }
3206 
3207 // -----------------------------------------------------------------------
3208 
3209 void WinSalFrame::SetBackgroundBitmap( SalBitmap* )
3210 {
3211 }
3212 
3213 // -----------------------------------------------------------------------
3214 
3215 void WinSalFrame::ResetClipRegion()
3216 {
3217 	SetWindowRgn( mhWnd, 0, TRUE );
3218 }
3219 
3220 // -----------------------------------------------------------------------
3221 
3222 void WinSalFrame::BeginSetClipRegion( sal_uLong nRects )
3223 {
3224     if( mpClipRgnData )
3225         delete [] (BYTE*)mpClipRgnData;
3226 	sal_uLong nRectBufSize = sizeof(RECT)*nRects;
3227     mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize];
3228 	mpClipRgnData->rdh.dwSize	  = sizeof( RGNDATAHEADER );
3229 	mpClipRgnData->rdh.iType	  = RDH_RECTANGLES;
3230 	mpClipRgnData->rdh.nCount	  = nRects;
3231 	mpClipRgnData->rdh.nRgnSize  = nRectBufSize;
3232 	SetRectEmpty( &(mpClipRgnData->rdh.rcBound) );
3233 	mpNextClipRect 		  = (RECT*)(&(mpClipRgnData->Buffer));
3234 	mbFirstClipRect		  = TRUE;
3235 }
3236 
3237 // -----------------------------------------------------------------------
3238 
3239 void WinSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
3240 {
3241     if( ! mpClipRgnData )
3242         return;
3243 
3244 	RECT*		pRect = mpNextClipRect;
3245 	RECT*		pBoundRect = &(mpClipRgnData->rdh.rcBound);
3246 	long		nRight = nX + nWidth;
3247 	long		nBottom = nY + nHeight;
3248 
3249 	if ( mbFirstClipRect )
3250 	{
3251 		pBoundRect->left	= nX;
3252 		pBoundRect->top 	= nY;
3253 		pBoundRect->right	= nRight;
3254 		pBoundRect->bottom	= nBottom;
3255 		mbFirstClipRect = FALSE;
3256 	}
3257 	else
3258 	{
3259 		if ( nX < pBoundRect->left )
3260 			pBoundRect->left = (int)nX;
3261 
3262 		if ( nY < pBoundRect->top )
3263 			pBoundRect->top = (int)nY;
3264 
3265 		if ( nRight > pBoundRect->right )
3266 			pBoundRect->right = (int)nRight;
3267 
3268 		if ( nBottom > pBoundRect->bottom )
3269 			pBoundRect->bottom = (int)nBottom;
3270 	}
3271 
3272 	pRect->left 	= (int)nX;
3273 	pRect->top		= (int)nY;
3274 	pRect->right	= (int)nRight;
3275 	pRect->bottom	= (int)nBottom;
3276     if( (mpNextClipRect  - (RECT*)(&mpClipRgnData->Buffer)) < (int)mpClipRgnData->rdh.nCount )
3277         mpNextClipRect++;
3278 }
3279 
3280 // -----------------------------------------------------------------------
3281 
3282 void WinSalFrame::EndSetClipRegion()
3283 {
3284     if( ! mpClipRgnData )
3285         return;
3286 
3287 	HRGN hRegion;
3288 
3289 	// create region from accumulated rectangles
3290 	if ( mpClipRgnData->rdh.nCount == 1 )
3291 	{
3292 		RECT* pRect = &(mpClipRgnData->rdh.rcBound);
3293 		hRegion = CreateRectRgn( pRect->left, pRect->top,
3294 								 pRect->right, pRect->bottom );
3295 	}
3296 	else
3297 	{
3298 		sal_uLong nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER);
3299 		hRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData );
3300 	}
3301     delete [] (BYTE*)mpClipRgnData;
3302     mpClipRgnData = NULL;
3303 
3304 	DBG_ASSERT( hRegion, "WinSalFrame::EndSetClipRegion() - Can't create ClipRegion" );
3305     if( hRegion )
3306     {
3307         RECT aWindowRect;
3308         GetWindowRect( mhWnd, &aWindowRect );
3309         POINT aPt;
3310         aPt.x=0;
3311         aPt.y=0;
3312         ClientToScreen( mhWnd, &aPt );
3313         OffsetRgn( hRegion, aPt.x - aWindowRect.left, aPt.y - aWindowRect.top );
3314 
3315         if( SetWindowRgn( mhWnd, hRegion, TRUE ) == 0 )
3316             DeleteObject( hRegion );
3317     }
3318 }
3319 
3320 // -----------------------------------------------------------------------
3321 
3322 static long ImplHandleMouseMsg( HWND hWnd, UINT nMsg,
3323                                 WPARAM wParam, LPARAM lParam )
3324 {
3325     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3326     if ( !pFrame )
3327         return 0;
3328 
3329     if( nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN || nMsg == WM_RBUTTONDOWN )
3330     {
3331         // #103168# post again if async focus has not arrived yet
3332         // hopefully we will not receive the corresponding button up before this
3333         // button down arrives again
3334         Window *pWin = pFrame->GetWindow();
3335         if( pWin && pWin->ImplGetWindowImpl()->mpFrameData->mnFocusId )
3336         {
3337             ImplPostMessage( hWnd, nMsg, wParam, lParam );
3338             return 1;
3339         }
3340     }
3341     SalMouseEvent   aMouseEvt;
3342     long            nRet;
3343     sal_uInt16          nEvent = 0;
3344     sal_Bool            bCall = TRUE;
3345 
3346     aMouseEvt.mnX       = (short)LOWORD( lParam );
3347     aMouseEvt.mnY       = (short)HIWORD( lParam );
3348     aMouseEvt.mnCode    = 0;
3349     aMouseEvt.mnTime    = GetMessageTime();
3350 
3351     // Wegen (Logitech-)MouseTreiber ueber GetKeyState() gehen, die auf
3352     // mittlerer Maustaste Doppelklick simulieren und den KeyStatus nicht
3353     // beruecksichtigen
3354 
3355     if ( GetKeyState( VK_LBUTTON ) & 0x8000 )
3356         aMouseEvt.mnCode |= MOUSE_LEFT;
3357     if ( GetKeyState( VK_MBUTTON ) & 0x8000 )
3358         aMouseEvt.mnCode |= MOUSE_MIDDLE;
3359     if ( GetKeyState( VK_RBUTTON ) & 0x8000 )
3360         aMouseEvt.mnCode |= MOUSE_RIGHT;
3361     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3362         aMouseEvt.mnCode |= KEY_SHIFT;
3363     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3364         aMouseEvt.mnCode |= KEY_MOD1;
3365     if ( GetKeyState( VK_MENU ) & 0x8000 )
3366         aMouseEvt.mnCode |= KEY_MOD2;
3367 
3368     switch ( nMsg )
3369     {
3370         case WM_MOUSEMOVE:
3371             {
3372             // Da bei Druecken von Modifier-Tasten die MouseEvents
3373             // nicht zusammengefast werden (da diese durch KeyEvents
3374             // unterbrochen werden), machen wir dieses hier selber
3375             if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) )
3376             {
3377                 MSG aTempMsg;
3378                 if ( ImplPeekMessage( &aTempMsg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE | PM_NOYIELD ) )
3379                 {
3380                     if ( (aTempMsg.message == WM_MOUSEMOVE) &&
3381                          (aTempMsg.wParam == wParam) )
3382                         return 1;
3383                 }
3384             }
3385 
3386             SalData* pSalData = GetSalData();
3387             // Test for MouseLeave
3388             if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) )
3389 				ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() );
3390 
3391             pSalData->mhWantLeaveMsg = hWnd;
3392             // Start MouseLeave-Timer
3393             if ( !pSalData->mpMouseLeaveTimer )
3394             {
3395                 pSalData->mpMouseLeaveTimer = new AutoTimer;
3396                 pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT );
3397                 pSalData->mpMouseLeaveTimer->Start();
3398                 // We dont need to set a timeout handler, because we test
3399                 // for mouseleave in the timeout callback
3400             }
3401             aMouseEvt.mnButton = 0;
3402             nEvent = SALEVENT_MOUSEMOVE;
3403             }
3404             break;
3405 
3406         case WM_NCMOUSEMOVE:
3407         case SAL_MSG_MOUSELEAVE:
3408             {
3409             SalData* pSalData = GetSalData();
3410             if ( pSalData->mhWantLeaveMsg == hWnd )
3411             {
3412                 pSalData->mhWantLeaveMsg = 0;
3413                 if ( pSalData->mpMouseLeaveTimer )
3414                 {
3415                     delete pSalData->mpMouseLeaveTimer;
3416                     pSalData->mpMouseLeaveTimer = NULL;
3417                 }
3418                 // Mouse-Coordinaates are relativ to the screen
3419                 POINT aPt;
3420                 aPt.x = (short)LOWORD( lParam );
3421                 aPt.y = (short)HIWORD( lParam );
3422                 ScreenToClient( hWnd, &aPt );
3423                 aMouseEvt.mnX = aPt.x;
3424                 aMouseEvt.mnY = aPt.y;
3425                 aMouseEvt.mnButton = 0;
3426                 nEvent = SALEVENT_MOUSELEAVE;
3427             }
3428             else
3429                 bCall = FALSE;
3430             }
3431             break;
3432 
3433         case WM_LBUTTONDOWN:
3434             aMouseEvt.mnButton = MOUSE_LEFT;
3435             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3436             break;
3437 
3438         case WM_MBUTTONDOWN:
3439             aMouseEvt.mnButton = MOUSE_MIDDLE;
3440             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3441             break;
3442 
3443         case WM_RBUTTONDOWN:
3444             aMouseEvt.mnButton = MOUSE_RIGHT;
3445             nEvent = SALEVENT_MOUSEBUTTONDOWN;
3446             break;
3447 
3448         case WM_LBUTTONUP:
3449             aMouseEvt.mnButton = MOUSE_LEFT;
3450             nEvent = SALEVENT_MOUSEBUTTONUP;
3451             break;
3452 
3453         case WM_MBUTTONUP:
3454             aMouseEvt.mnButton = MOUSE_MIDDLE;
3455             nEvent = SALEVENT_MOUSEBUTTONUP;
3456             break;
3457 
3458         case WM_RBUTTONUP:
3459             aMouseEvt.mnButton = MOUSE_RIGHT;
3460             nEvent = SALEVENT_MOUSEBUTTONUP;
3461             break;
3462     }
3463 
3464 	// check if this window was destroyed - this might happen if we are the help window
3465 	// and sent a mouse leave message to the application which killed the help window, ie ourself
3466 	if( !IsWindow( hWnd ) )
3467 		return 0;
3468 
3469     if ( bCall )
3470     {
3471         if ( nEvent == SALEVENT_MOUSEBUTTONDOWN )
3472             UpdateWindow( hWnd );
3473 
3474         // --- RTL --- (mirror mouse pos)
3475         if( Application::GetSettings().GetLayoutRTL() )
3476             aMouseEvt.mnX = pFrame->maGeometry.nWidth-1-aMouseEvt.mnX;
3477 
3478         nRet = pFrame->CallCallback( nEvent, &aMouseEvt );
3479         if ( nMsg == WM_MOUSEMOVE )
3480             SetCursor( pFrame->mhCursor );
3481     }
3482     else
3483         nRet = 0;
3484 
3485     return nRet;
3486 }
3487 
3488 // -----------------------------------------------------------------------
3489 
3490 static long ImplHandleMouseActivateMsg( HWND hWnd )
3491 {
3492     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3493     if ( !pFrame )
3494         return 0;
3495 
3496     if ( pFrame->mbFloatWin )
3497         return TRUE;
3498 
3499     SalMouseActivateEvent   aMouseActivateEvt;
3500     POINT                   aPt;
3501     GetCursorPos( &aPt );
3502     ScreenToClient( hWnd, &aPt );
3503     aMouseActivateEvt.mnX = aPt.x;
3504     aMouseActivateEvt.mnY = aPt.y;
3505     return pFrame->CallCallback( SALEVENT_MOUSEACTIVATE, &aMouseActivateEvt );
3506 }
3507 
3508 // -----------------------------------------------------------------------
3509 
3510 static long ImplHandleWheelMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
3511 {
3512     DBG_ASSERT( nMsg == WM_MOUSEWHEEL ||
3513                 nMsg == WM_MOUSEHWHEEL,
3514                 "ImplHandleWheelMsg() called with no wheel mouse event" );
3515 
3516     ImplSalYieldMutexAcquireWithWait();
3517 
3518     long        nRet = 0;
3519     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
3520     if ( pFrame )
3521     {
3522         WORD    nWinModCode = LOWORD( wParam );
3523         POINT   aWinPt;
3524         aWinPt.x    = (short)LOWORD( lParam );
3525         aWinPt.y    = (short)HIWORD( lParam );
3526         ScreenToClient( hWnd, &aWinPt );
3527 
3528         SalWheelMouseEvent aWheelEvt;
3529         aWheelEvt.mnTime        = GetMessageTime();
3530         aWheelEvt.mnX           = aWinPt.x;
3531         aWheelEvt.mnY           = aWinPt.y;
3532         aWheelEvt.mnCode        = 0;
3533         aWheelEvt.mnDelta       = (short)HIWORD( wParam );
3534         aWheelEvt.mnNotchDelta  = aWheelEvt.mnDelta/WHEEL_DELTA;
3535         if( aWheelEvt.mnNotchDelta == 0 )
3536         {
3537             if( aWheelEvt.mnDelta > 0 )
3538                 aWheelEvt.mnNotchDelta = 1;
3539             else if( aWheelEvt.mnDelta < 0 )
3540                 aWheelEvt.mnNotchDelta = -1;
3541         }
3542 
3543         if( nMsg == WM_MOUSEWHEEL )
3544         {
3545             if ( aSalShlData.mnWheelScrollLines == WHEEL_PAGESCROLL )
3546                 aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
3547             else
3548                 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollLines;
3549             aWheelEvt.mbHorz        = FALSE;
3550         }
3551         else
3552         {
3553             aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollChars;
3554             aWheelEvt.mbHorz        = TRUE;
3555         }
3556 
3557         if ( nWinModCode & MK_SHIFT )
3558             aWheelEvt.mnCode |= KEY_SHIFT;
3559         if ( nWinModCode & MK_CONTROL )
3560             aWheelEvt.mnCode |= KEY_MOD1;
3561         if ( GetKeyState( VK_MENU ) & 0x8000 )
3562             aWheelEvt.mnCode |= KEY_MOD2;
3563 
3564         // --- RTL --- (mirror mouse pos)
3565         if( Application::GetSettings().GetLayoutRTL() )
3566             aWheelEvt.mnX = pFrame->maGeometry.nWidth-1-aWheelEvt.mnX;
3567 
3568         nRet = pFrame->CallCallback( SALEVENT_WHEELMOUSE, &aWheelEvt );
3569     }
3570 
3571     ImplSalYieldMutexRelease();
3572 
3573     return nRet;
3574 }
3575 
3576 // -----------------------------------------------------------------------
3577 
3578 static sal_uInt16 ImplSalGetKeyCode( WPARAM wParam )
3579 {
3580     sal_uInt16 nKeyCode;
3581 
3582     // convert KeyCode
3583     if ( wParam < KEY_TAB_SIZE )
3584         nKeyCode = aImplTranslateKeyTab[wParam];
3585 	else
3586 	{
3587 		SalData* pSalData = GetSalData();
3588 		std::map< UINT, sal_uInt16 >::const_iterator it = pSalData->maVKMap.find( (UINT)wParam );
3589 		if( it != pSalData->maVKMap.end() )
3590 			nKeyCode = it->second;
3591 		else
3592 			nKeyCode = 0;
3593 	}
3594 
3595     return nKeyCode;
3596 }
3597 
3598 // -----------------------------------------------------------------------
3599 
3600 static UINT ImplStrToNum( const sal_Char* pStr )
3601 {
3602     sal_uInt16 n = 0;
3603 
3604     // Solange es sich um eine Ziffer handelt, String umwandeln
3605     while( (*pStr >= 48) && (*pStr <= 57) )
3606     {
3607         n *= 10;
3608         n += ((*pStr) - 48);
3609         pStr++;
3610     }
3611 
3612     return n;
3613 }
3614 
3615 // -----------------------------------------------------------------------
3616 
3617 static void ImplUpdateInputLang( WinSalFrame* pFrame )
3618 {
3619     sal_Bool bLanguageChange = FALSE;
3620     UINT nLang = LOWORD( GetKeyboardLayout( 0 ) );
3621     if ( nLang && nLang != pFrame->mnInputLang )
3622     {
3623         // keep input lang up-to-date
3624         pFrame->mnInputLang = nLang;
3625         bLanguageChange = TRUE;
3626     }
3627 
3628     // If we are on Windows NT we use Unicode FrameProcs and so we
3629     // get Unicode charcodes directly from Windows
3630     // no need to set up a code page
3631     return;
3632 }
3633 
3634 
3635 static sal_Unicode ImplGetCharCode( WinSalFrame* pFrame, WPARAM nCharCode )
3636 {
3637     ImplUpdateInputLang( pFrame );
3638 
3639     // If we are on Windows NT we use Unicode FrameProcs and so we
3640     // get Unicode charcodes directly from Windows
3641     return (sal_Unicode)nCharCode;
3642 }
3643 
3644 // -----------------------------------------------------------------------
3645 
3646 LanguageType WinSalFrame::GetInputLanguage()
3647 {
3648     if( !mnInputLang )
3649         ImplUpdateInputLang( this );
3650 
3651     if( !mnInputLang )
3652         return LANGUAGE_DONTKNOW;
3653     else
3654         return (LanguageType) mnInputLang;
3655 }
3656 
3657 // -----------------------------------------------------------------------
3658 
3659 sal_Bool WinSalFrame::MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode )
3660 {
3661     sal_Bool bRet = FALSE;
3662     HKL hkl = 0;
3663 
3664     // just use the passed language identifier, do not try to load additional keyboard support
3665     hkl = (HKL) aLangType;
3666 
3667     if( hkl )
3668     {
3669         SHORT scan = VkKeyScanExW( aUnicode, hkl );
3670         if( LOWORD(scan) == 0xFFFF )
3671             // keyboard not loaded or key cannot be mapped
3672             bRet = FALSE;
3673         else
3674         {
3675             BYTE vkeycode   = LOBYTE(scan);
3676             BYTE shiftstate = HIBYTE(scan);
3677 
3678             // Last argument is set to FALSE, because there's no decission made
3679             // yet which key should be assigned to MOD3 modifier on Windows.
3680             // Windows key - user's can be confused, because it should display
3681             //               Windows menu (applies to both left/right key)
3682             // Menu key    - this key is used to display context menu
3683             // AltGr key   - probably it has no sense
3684             rKeyCode = KeyCode( ImplSalGetKeyCode( vkeycode ),
3685                 (shiftstate & 0x01) ? TRUE : FALSE,     // shift
3686                 (shiftstate & 0x02) ? TRUE : FALSE,     // ctrl
3687                 (shiftstate & 0x04) ? TRUE : FALSE,     // alt
3688                 FALSE );
3689             bRet = TRUE;
3690         }
3691     }
3692 
3693     return bRet;
3694 }
3695 
3696 // -----------------------------------------------------------------------
3697 
3698 static long ImplHandleKeyMsg( HWND hWnd, UINT nMsg,
3699                               WPARAM wParam, LPARAM lParam, LRESULT& rResult )
3700 {
3701     static sal_Bool     bIgnoreCharMsg  = FALSE;
3702     static WPARAM   nDeadChar       = 0;
3703     static WPARAM   nLastVKChar     = 0;
3704     static sal_uInt16   nLastChar       = 0;
3705     static sal_uInt16   nLastModKeyCode = 0;
3706     static bool     bWaitForModKeyRelease = false;
3707     sal_uInt16          nRepeat         = LOWORD( lParam )-1;
3708     sal_uInt16          nModCode        = 0;
3709 
3710     // Key wurde evtl. durch SysChild an uns weitergeleitet und
3711     // darf somit dann nicht doppelt verarbeitet werden
3712     GetSalData()->mnSalObjWantKeyEvt = 0;
3713 
3714     if ( nMsg == WM_DEADCHAR )
3715     {
3716         nDeadChar = wParam;
3717         return 0;
3718     }
3719 
3720     WinSalFrame* pFrame = GetWindowPtr( hWnd );
3721     if ( !pFrame )
3722         return 0;
3723 
3724     // Wir restaurieren den Background-Modus bei jeder Texteingabe,
3725     // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
3726     if ( pFrame->mpGraphics &&
3727          pFrame->mpGraphics->getHDC() )
3728         SetBkMode( pFrame->mpGraphics->getHDC(), TRANSPARENT );
3729 
3730     // determine modifiers
3731     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3732         nModCode |= KEY_SHIFT;
3733     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
3734         nModCode |= KEY_MOD1;
3735     if ( GetKeyState( VK_MENU ) & 0x8000 )
3736         nModCode |= KEY_MOD2;
3737 
3738     if ( (nMsg == WM_CHAR) || (nMsg == WM_SYSCHAR) )
3739     {
3740         nDeadChar = 0;
3741 
3742         if ( bIgnoreCharMsg )
3743         {
3744             bIgnoreCharMsg = FALSE;
3745             // #101635# if zero is returned here for WM_SYSCHAR (ALT+<key>) Windows will beep
3746             // becaus this 'hotkey' was not processed -> better return 1
3747             // except for Alt-SPACE which should always open the sysmenu (#104616#)
3748 
3749             // also return zero if a system menubar is available that might process this hotkey
3750             // this also applies to the OLE inplace embedding where we are a child window
3751             if( (GetWindowStyle( hWnd ) & WS_CHILD) || GetMenu( hWnd ) || (wParam == 0x20) )
3752                 return 0;
3753             else
3754                 return 1;
3755         }
3756 
3757         // Backspace ignorieren wir als eigenstaendige Taste,
3758         // damit wir keine Probleme in Kombination mit einem
3759         // DeadKey bekommen
3760         if ( wParam == 0x08 )    // BACKSPACE
3761             return 0;
3762 
3763         // Hier kommen nur "freifliegende" WM_CHAR Message an, die durch
3764         // eintippen einer ALT-NUMPAD Kombination erzeugt wurden
3765         SalKeyEvent aKeyEvt;
3766 
3767         if ( (wParam >= '0') && (wParam <= '9') )
3768             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_NUM + wParam - '0');
3769         else if ( (wParam >= 'A') && (wParam <= 'Z') )
3770             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'A');
3771         else if ( (wParam >= 'a') && (wParam <= 'z') )
3772             aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'a');
3773         else if ( wParam == 0x0D )    // RETURN
3774             aKeyEvt.mnCode = KEY_RETURN;
3775         else if ( wParam == 0x1B )    // ESCAPE
3776             aKeyEvt.mnCode = KEY_ESCAPE;
3777         else if ( wParam == 0x09 )    // TAB
3778             aKeyEvt.mnCode = KEY_TAB;
3779         else if ( wParam == 0x20 )    // SPACE
3780             aKeyEvt.mnCode = KEY_SPACE;
3781         else
3782             aKeyEvt.mnCode = 0;
3783 
3784         aKeyEvt.mnTime      = GetMessageTime();
3785         aKeyEvt.mnCode     |= nModCode;
3786         aKeyEvt.mnCharCode  = ImplGetCharCode( pFrame, wParam );
3787         aKeyEvt.mnRepeat    = nRepeat;
3788         nLastChar = 0;
3789         nLastVKChar = 0;
3790         long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3791         pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3792         return nRet;
3793     }
3794  	// #i11583#, MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition begins
3795 	else if( nMsg == WM_UNICHAR )
3796  	{
3797  		// If Windows is asking if we accept WM_UNICHAR, return TRUE
3798  		if(wParam == UNICODE_NOCHAR)
3799         {
3800             rResult = TRUE; // ssa: this will actually return TRUE to windows
3801             return 1;       // ...but this will only avoid calling the defwindowproc
3802         }
3803 
3804  		SalKeyEvent aKeyEvt;
3805  		aKeyEvt.mnCode		= nModCode;	// Or should it be 0? - as this is always a character returned
3806  		aKeyEvt.mnTime		= GetMessageTime();
3807  		aKeyEvt.mnRepeat	= 0;
3808 
3809 		if( wParam >= Uni_SupplementaryPlanesStart )
3810 		{
3811 			// character is supplementary char in UTF-32 format - must be converted to UTF-16 supplementary pair
3812 			// sal_Unicode ch = (sal_Unicode) Uni_UTF32ToSurrogate1(wParam);
3813 	 		nLastChar = 0;
3814  			nLastVKChar = 0;
3815 	 		pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3816  			pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3817 			wParam = (sal_Unicode) Uni_UTF32ToSurrogate2( wParam );
3818  		}
3819 
3820  		aKeyEvt.mnCharCode	= (sal_Unicode) wParam;
3821 
3822  		nLastChar = 0;
3823  		nLastVKChar = 0;
3824  		long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
3825  		pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3826 
3827  		return nRet;
3828  	}
3829  	// MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition ends
3830     else
3831     {
3832         // Bei Shift, Control und Menu schicken wir einen KeyModChange-Event
3833         if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) )
3834         {
3835             SalKeyModEvent aModEvt;
3836             aModEvt.mnTime = GetMessageTime();
3837             aModEvt.mnCode = nModCode;
3838             aModEvt.mnModKeyCode = 0;   // no command events will be sent if this member is 0
3839 
3840             sal_uInt16 tmpCode = 0;
3841             if( GetKeyState( VK_LSHIFT )  & 0x8000 )
3842                 tmpCode |= MODKEY_LSHIFT;
3843             if( GetKeyState( VK_RSHIFT )  & 0x8000 )
3844                 tmpCode |= MODKEY_RSHIFT;
3845             if( GetKeyState( VK_LCONTROL ) & 0x8000 )
3846                 tmpCode |= MODKEY_LMOD1;
3847             if( GetKeyState( VK_RCONTROL ) & 0x8000 )
3848                 tmpCode |= MODKEY_RMOD1;
3849             if( GetKeyState( VK_LMENU )  & 0x8000 )
3850                 tmpCode |= MODKEY_LMOD2;
3851             if( GetKeyState( VK_RMENU )  & 0x8000 )
3852                 tmpCode |= MODKEY_RMOD2;
3853 
3854             if( tmpCode < nLastModKeyCode )
3855             {
3856                 aModEvt.mnModKeyCode = nLastModKeyCode;
3857                 nLastModKeyCode = 0;
3858                 bWaitForModKeyRelease = true;
3859             }
3860             else
3861             {
3862                 if( !bWaitForModKeyRelease )
3863                     nLastModKeyCode = tmpCode;
3864             }
3865 
3866             if( !tmpCode )
3867                 bWaitForModKeyRelease = false;
3868 
3869             return pFrame->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
3870         }
3871         else
3872         {
3873             SalKeyEvent     aKeyEvt;
3874             sal_uInt16          nEvent;
3875             MSG             aCharMsg;
3876             BOOL        bCharPeek = FALSE;
3877             UINT            nCharMsg = WM_CHAR;
3878             sal_Bool            bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
3879 
3880             nLastModKeyCode = 0; // make sure no modkey messages are sent if they belong to a hotkey (see above)
3881             aKeyEvt.mnCharCode = 0;
3882             aKeyEvt.mnCode = 0;
3883 
3884             aKeyEvt.mnCode = ImplSalGetKeyCode( wParam );
3885             if ( !bKeyUp )
3886             {
3887                 // check for charcode
3888                 // Mit Hilfe von PeekMessage holen wir uns jetzt die
3889                 // zugehoerige WM_CHAR Message, wenn vorhanden.
3890                 // Diese WM_CHAR Message steht immer am Anfang der
3891                 // Messagequeue. Ausserdem ist sichergestellt, dass immer
3892                 // nur eine WM_CHAR Message in der Queue steht.
3893                 bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
3894                                              WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD );
3895                 if ( bCharPeek && (nDeadChar == aCharMsg.wParam) )
3896                 {
3897                     bCharPeek = FALSE;
3898                     nDeadChar = 0;
3899 
3900                     if ( wParam == VK_BACK )
3901                     {
3902                         ImplPeekMessage( &aCharMsg, hWnd,
3903                                          nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
3904                         return 0;
3905                     }
3906                 }
3907                 else
3908                 {
3909                     if ( !bCharPeek )
3910                     {
3911                         bCharPeek = ImplPeekMessage( &aCharMsg, hWnd,
3912                                                     WM_SYSCHAR, WM_SYSCHAR, PM_NOREMOVE | PM_NOYIELD );
3913                         nCharMsg = WM_SYSCHAR;
3914                     }
3915                 }
3916                 if ( bCharPeek )
3917                     aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, aCharMsg.wParam );
3918                 else
3919                     aKeyEvt.mnCharCode = 0;
3920 
3921                 nLastChar = aKeyEvt.mnCharCode;
3922                 nLastVKChar = wParam;
3923             }
3924             else
3925             {
3926                 if ( wParam == nLastVKChar )
3927                 {
3928                     aKeyEvt.mnCharCode = nLastChar;
3929                     nLastChar = 0;
3930                     nLastVKChar = 0;
3931                 }
3932             }
3933 
3934             if ( aKeyEvt.mnCode || aKeyEvt.mnCharCode )
3935             {
3936                 if ( bKeyUp )
3937                     nEvent = SALEVENT_KEYUP;
3938                 else
3939                     nEvent = SALEVENT_KEYINPUT;
3940 
3941                 aKeyEvt.mnTime      = GetMessageTime();
3942                 aKeyEvt.mnCode     |= nModCode;
3943                 aKeyEvt.mnRepeat    = nRepeat;
3944 
3945                 if( (nModCode & (KEY_MOD1|KEY_MOD2)) == (KEY_MOD1|KEY_MOD2) &&
3946                     aKeyEvt.mnCharCode )
3947                 {
3948                      // this is actually AltGr and should not be handled as Alt
3949                      aKeyEvt.mnCode &= ~(KEY_MOD1|KEY_MOD2);
3950                 }
3951 
3952                 bIgnoreCharMsg = bCharPeek ? TRUE : FALSE;
3953                 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt );
3954                 // independent part only reacts on keyup but Windows does not send
3955                 // keyup for VK_HANJA
3956                 if( aKeyEvt.mnCode == KEY_HANGUL_HANJA )
3957                     nRet = pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
3958 
3959                 bIgnoreCharMsg = FALSE;
3960 
3961                 // char-message, than remove or ignore
3962                 if ( bCharPeek )
3963                 {
3964                     nDeadChar = 0;
3965                     if ( nRet )
3966                     {
3967                         ImplPeekMessage( &aCharMsg, hWnd,
3968                                          nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD );
3969                     }
3970                     else
3971                         bIgnoreCharMsg = TRUE;
3972                 }
3973 
3974                 return nRet;
3975             }
3976             else
3977                 return 0;
3978         }
3979     }
3980 }
3981 
3982 // -----------------------------------------------------------------------
3983 
3984 long ImplHandleSalObjKeyMsg( HWND hWnd, UINT nMsg,
3985                              WPARAM wParam, LPARAM lParam )
3986 {
3987     if ( (nMsg == WM_KEYDOWN) || (nMsg == WM_KEYUP) )
3988     {
3989         WinSalFrame* pFrame = GetWindowPtr( hWnd );
3990         if ( !pFrame )
3991             return 0;
3992 
3993         sal_uInt16  nRepeat     = LOWORD( lParam )-1;
3994         sal_uInt16  nModCode    = 0;
3995 
3996         // determine modifiers
3997         if ( GetKeyState( VK_SHIFT ) & 0x8000 )
3998             nModCode |= KEY_SHIFT;
3999         if ( GetKeyState( VK_CONTROL ) & 0x8000 )
4000             nModCode |= KEY_MOD1;
4001         if ( GetKeyState( VK_MENU ) & 0x8000 )
4002             nModCode |= KEY_MOD2;
4003 
4004         if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) && (wParam != VK_MENU) )
4005         {
4006             SalKeyEvent     aKeyEvt;
4007             sal_uInt16          nEvent;
4008             sal_Bool            bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP);
4009 
4010             // convert KeyCode
4011             aKeyEvt.mnCode      = ImplSalGetKeyCode( wParam );
4012             aKeyEvt.mnCharCode  = 0;
4013 
4014             if ( aKeyEvt.mnCode )
4015             {
4016                 if ( bKeyUp )
4017                     nEvent = SALEVENT_KEYUP;
4018                 else
4019                     nEvent = SALEVENT_KEYINPUT;
4020 
4021                 aKeyEvt.mnTime      = GetMessageTime();
4022                 aKeyEvt.mnCode     |= nModCode;
4023                 aKeyEvt.mnRepeat    = nRepeat;
4024                 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt );
4025                 return nRet;
4026             }
4027             else
4028                 return 0;
4029         }
4030     }
4031 
4032     return 0;
4033 }
4034 
4035 // -----------------------------------------------------------------------
4036 
4037 long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
4038 {
4039     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4040     if ( !pFrame )
4041         return 0;
4042 
4043     sal_uInt16  nRepeat     = LOWORD( lParam )-1;
4044     sal_uInt16  nModCode    = 0;
4045     sal_uInt16  cKeyCode    = (sal_uInt16)wParam;
4046 
4047     // determine modifiers
4048     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
4049         nModCode |= KEY_SHIFT;
4050     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
4051         nModCode |= KEY_MOD1;
4052     nModCode |= KEY_MOD2;
4053 
4054     // KeyEvent zusammenbauen
4055     SalKeyEvent aKeyEvt;
4056     aKeyEvt.mnTime      = GetMessageTime();
4057     if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
4058         aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
4059     else if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
4060         aKeyEvt.mnCode = KEY_A+(cKeyCode-65);
4061     else  if ( (cKeyCode >= 97) && (cKeyCode <= 122) )
4062         aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
4063     else
4064         aKeyEvt.mnCode = 0;
4065     aKeyEvt.mnCode     |= nModCode;
4066     aKeyEvt.mnCharCode  = ImplGetCharCode( pFrame, cKeyCode );
4067     aKeyEvt.mnRepeat    = nRepeat;
4068     long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
4069     pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
4070     return nRet;
4071 }
4072 
4073 // -----------------------------------------------------------------------
4074 
4075 static bool ImplHandlePaintMsg( HWND hWnd )
4076 {
4077     sal_Bool bMutex = FALSE;
4078     if ( ImplSalYieldMutexTryToAcquire() )
4079         bMutex = TRUE;
4080 
4081     // if we don't get the mutex, we can also change the clip region,
4082     // because other threads doesn't use the mutex from the main
4083     // thread --> see GetGraphics()
4084 
4085     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4086     if ( pFrame )
4087     {
4088         // Clip-Region muss zurueckgesetzt werden, da wir sonst kein
4089         // ordentliches Bounding-Rectangle bekommen
4090         if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4091             SelectClipRgn( pFrame->mpGraphics->getHDC(), 0 );
4092 
4093         // Laut Window-Doku soll man erst abfragen, ob ueberhaupt eine
4094         // Paint-Region anliegt
4095         if ( GetUpdateRect( hWnd, NULL, FALSE ) )
4096         {
4097             // Call BeginPaint/EndPaint to query the rect and send
4098             // this Notofication to rect
4099             RECT aUpdateRect;
4100             PAINTSTRUCT aPs;
4101             BeginPaint( hWnd, &aPs );
4102             CopyRect( &aUpdateRect, &aPs.rcPaint );
4103 
4104             // Paint
4105             // ClipRegion wieder herstellen
4106             if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4107             {
4108                 SelectClipRgn( pFrame->mpGraphics->getHDC(),
4109                                pFrame->mpGraphics->mhRegion );
4110             }
4111 
4112             if ( bMutex )
4113             {
4114                 SalPaintEvent aPEvt( aUpdateRect.left, aUpdateRect.top, aUpdateRect.right-aUpdateRect.left, aUpdateRect.bottom-aUpdateRect.top, pFrame->mbPresentation );
4115                 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
4116             }
4117             else
4118             {
4119                 RECT* pRect = new RECT;
4120                 CopyRect( pRect, &aUpdateRect );
4121                 ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
4122             }
4123             EndPaint( hWnd, &aPs );
4124         }
4125         else
4126         {
4127             // ClipRegion wieder herstellen
4128             if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion )
4129             {
4130                 SelectClipRgn( pFrame->mpGraphics->getHDC(),
4131                                pFrame->mpGraphics->mhRegion );
4132             }
4133         }
4134     }
4135 
4136     if ( bMutex )
4137         ImplSalYieldMutexRelease();
4138 
4139 	return bMutex ? true : false;
4140 }
4141 
4142 // -----------------------------------------------------------------------
4143 
4144 static void ImplHandlePaintMsg2( HWND hWnd, RECT* pRect )
4145 {
4146     // Paint
4147     if ( ImplSalYieldMutexTryToAcquire() )
4148     {
4149         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4150         if ( pFrame )
4151         {
4152             SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top );
4153             pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
4154         }
4155         ImplSalYieldMutexRelease();
4156         delete pRect;
4157     }
4158     else
4159         ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 );
4160 }
4161 
4162 // -----------------------------------------------------------------------
4163 
4164 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect )
4165 {
4166     // calculate and set frame geometry of a maximized window - useful if the window is still hidden
4167 
4168     // dualmonitor support:
4169     // Get screensize of the monitor whith the mouse pointer
4170 
4171     RECT aRectMouse;
4172     if( ! pParentRect )
4173     {
4174         POINT pt;
4175         GetCursorPos( &pt );
4176         aRectMouse.left = pt.x;
4177         aRectMouse.top = pt.y;
4178         aRectMouse.right = pt.x+2;
4179         aRectMouse.bottom = pt.y+2;
4180         pParentRect = &aRectMouse;
4181     }
4182 
4183     RECT aRect;
4184     ImplSalGetWorkArea( hWnd, &aRect, pParentRect );
4185 
4186     // a maximized window has no other borders than the caption
4187     pFrame->maGeometry.nLeftDecoration = pFrame->maGeometry.nRightDecoration = pFrame->maGeometry.nBottomDecoration = 0;
4188     pFrame->maGeometry.nTopDecoration = pFrame->mbCaption ? GetSystemMetrics( SM_CYCAPTION ) : 0;
4189 
4190     aRect.top += pFrame->maGeometry.nTopDecoration;
4191     pFrame->maGeometry.nX = aRect.left;
4192     pFrame->maGeometry.nY = aRect.top;
4193     pFrame->maGeometry.nWidth = aRect.right - aRect.left;
4194     pFrame->maGeometry.nHeight = aRect.bottom - aRect.top;
4195 }
4196 
4197 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame )
4198 {
4199     if( !pFrame )
4200         return;
4201 
4202     RECT aRect;
4203     GetWindowRect( hWnd, &aRect );
4204     memset(&pFrame->maGeometry, 0, sizeof(SalFrameGeometry) );
4205 
4206     if ( IsIconic( hWnd ) )
4207         return;
4208 
4209     POINT aPt;
4210     aPt.x=0;
4211     aPt.y=0;
4212     ClientToScreen(hWnd, &aPt);
4213     int cx = aPt.x - aRect.left;
4214     pFrame->maGeometry.nTopDecoration = aPt.y - aRect.top;
4215 
4216     pFrame->maGeometry.nLeftDecoration = cx;
4217     pFrame->maGeometry.nRightDecoration = cx;
4218 
4219     pFrame->maGeometry.nX = aPt.x;
4220     pFrame->maGeometry.nY = aPt.y;
4221 
4222     RECT aInnerRect;
4223     GetClientRect( hWnd, &aInnerRect );
4224     if( aInnerRect.right )
4225     {
4226         // improve right decoration
4227         aPt.x=aInnerRect.right;
4228         aPt.y=aInnerRect.top;
4229         ClientToScreen(hWnd, &aPt);
4230         pFrame->maGeometry.nRightDecoration = aRect.right - aPt.x;
4231     }
4232     if( aInnerRect.bottom ) // may be zero if window was not shown yet
4233         pFrame->maGeometry.nBottomDecoration += aRect.bottom - aPt.y - aInnerRect.bottom;
4234     else
4235         // bottom border is typically the same as left/right
4236         pFrame->maGeometry.nBottomDecoration = pFrame->maGeometry.nLeftDecoration;
4237 
4238     int nWidth  = aRect.right - aRect.left
4239         - pFrame->maGeometry.nRightDecoration - pFrame->maGeometry.nLeftDecoration;
4240     int nHeight = aRect.bottom - aRect.top
4241         - pFrame->maGeometry.nBottomDecoration - pFrame->maGeometry.nTopDecoration;
4242     // clamp to zero
4243     pFrame->maGeometry.nHeight = nHeight < 0 ? 0 : nHeight;
4244     pFrame->maGeometry.nWidth = nWidth < 0 ? 0 : nWidth;
4245     pFrame->updateScreenNumber();
4246 }
4247 
4248 // -----------------------------------------------------------------------
4249 
4250 static void ImplCallMoveHdl( HWND hWnd )
4251 {
4252     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4253     if ( pFrame )
4254     {
4255         pFrame->CallCallback( SALEVENT_MOVE, 0 );
4256         // Um doppelte Paints von VCL und SAL zu vermeiden
4257         //if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4258         //    UpdateWindow( hWnd );
4259     }
4260 }
4261 
4262 // -----------------------------------------------------------------------
4263 
4264 static void ImplCallClosePopupsHdl( HWND hWnd )
4265 {
4266     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4267     if ( pFrame )
4268     {
4269         pFrame->CallCallback( SALEVENT_CLOSEPOPUPS, 0 );
4270     }
4271 }
4272 
4273 // -----------------------------------------------------------------------
4274 
4275 static void ImplHandleMoveMsg( HWND hWnd )
4276 {
4277     if ( ImplSalYieldMutexTryToAcquire() )
4278     {
4279         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4280         if ( pFrame )
4281         {
4282             UpdateFrameGeometry( hWnd, pFrame );
4283 
4284             if ( GetWindowStyle( hWnd ) & WS_VISIBLE )
4285                 pFrame->mbDefPos = FALSE;
4286 
4287             // Gegen moegliche Rekursionen sichern
4288             if ( !pFrame->mbInMoveMsg )
4289             {
4290                 // Fenster im FullScreenModus wieder einpassen
4291                 pFrame->mbInMoveMsg = TRUE;
4292                 if ( pFrame->mbFullScreen )
4293                     ImplSalFrameFullScreenPos( pFrame );
4294                 pFrame->mbInMoveMsg = FALSE;
4295             }
4296 
4297             // Status merken
4298             ImplSaveFrameState( pFrame );
4299 
4300             // Call Hdl
4301             //#93851 if we call this handler, VCL floating windows are not updated correctly
4302             ImplCallMoveHdl( hWnd );
4303 
4304         }
4305 
4306         ImplSalYieldMutexRelease();
4307     }
4308     else
4309         ImplPostMessage( hWnd, SAL_MSG_POSTMOVE, 0, 0 );
4310 }
4311 
4312 // -----------------------------------------------------------------------
4313 
4314 static void ImplCallSizeHdl( HWND hWnd )
4315 {
4316     // Da Windows diese Messages auch senden kann, muss hier auch die
4317     // Solar-Semaphore beruecksichtigt werden
4318     if ( ImplSalYieldMutexTryToAcquire() )
4319     {
4320         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4321         if ( pFrame )
4322         {
4323             pFrame->CallCallback( SALEVENT_RESIZE, 0 );
4324             // Um doppelte Paints von VCL und SAL zu vermeiden
4325             if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4326                 UpdateWindow( hWnd );
4327         }
4328 
4329         ImplSalYieldMutexRelease();
4330     }
4331     else
4332         ImplPostMessage( hWnd, SAL_MSG_POSTCALLSIZE, 0, 0 );
4333 }
4334 
4335 // -----------------------------------------------------------------------
4336 
4337 static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam )
4338 {
4339     if ( (wParam != SIZE_MAXSHOW) && (wParam != SIZE_MAXHIDE) )
4340     {
4341         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4342         if ( pFrame )
4343         {
4344             UpdateFrameGeometry( hWnd, pFrame );
4345 
4346             pFrame->mnWidth  = (int)LOWORD(lParam);
4347             pFrame->mnHeight = (int)HIWORD(lParam);
4348             // Status merken
4349             ImplSaveFrameState( pFrame );
4350             // Call Hdl
4351             ImplCallSizeHdl( hWnd );
4352         }
4353     }
4354 }
4355 
4356 // -----------------------------------------------------------------------
4357 
4358 static void ImplHandleFocusMsg( HWND hWnd )
4359 {
4360     if ( ImplSalYieldMutexTryToAcquire() )
4361     {
4362         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4363         if ( pFrame && !WinSalFrame::mbInReparent )
4364         {
4365             // Query the actual status
4366             if ( ::GetFocus() == hWnd )
4367             {
4368                 if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow )
4369                     UpdateWindow( hWnd );
4370 
4371                 // Feststellen, ob wir IME unterstuetzen
4372                 if ( pFrame->mbIME && pFrame->mhDefIMEContext )
4373                 {
4374                     UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY );
4375 
4376                     pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
4377                     pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
4378                     pFrame->mbHandleIME = !pFrame->mbSpezIME;
4379                 }
4380 
4381                 pFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
4382             }
4383             else
4384             {
4385                 pFrame->CallCallback( SALEVENT_LOSEFOCUS, 0 );
4386             }
4387         }
4388 
4389         ImplSalYieldMutexRelease();
4390     }
4391     else
4392         ImplPostMessage( hWnd, SAL_MSG_POSTFOCUS, 0, 0 );
4393 }
4394 
4395 // -----------------------------------------------------------------------
4396 
4397 static void ImplHandleCloseMsg( HWND hWnd )
4398 {
4399     if ( ImplSalYieldMutexTryToAcquire() )
4400     {
4401         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4402         if ( pFrame )
4403         {
4404             pFrame->CallCallback( SALEVENT_CLOSE, 0 );
4405         }
4406 
4407         ImplSalYieldMutexRelease();
4408     }
4409     else
4410         ImplPostMessage( hWnd, WM_CLOSE, 0, 0 );
4411 }
4412 
4413 // -----------------------------------------------------------------------
4414 
4415 static long ImplHandleShutDownMsg( HWND hWnd )
4416 {
4417     ImplSalYieldMutexAcquireWithWait();
4418     long        nRet = 0;
4419     WinSalFrame*   pFrame = GetWindowPtr( hWnd );
4420     if ( pFrame )
4421     {
4422         nRet = pFrame->CallCallback( SALEVENT_SHUTDOWN, 0 );
4423     }
4424     ImplSalYieldMutexRelease();
4425     return nRet;
4426 }
4427 
4428 // -----------------------------------------------------------------------
4429 
4430 static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg,
4431                                          WPARAM wParam, LPARAM lParam )
4432 {
4433     sal_uInt16 nSalEvent = SALEVENT_SETTINGSCHANGED;
4434 
4435     if ( nMsg == WM_DEVMODECHANGE )
4436         nSalEvent = SALEVENT_PRINTERCHANGED;
4437     else if ( nMsg == WM_DISPLAYCHANGE )
4438         nSalEvent = SALEVENT_DISPLAYCHANGED;
4439     else if ( nMsg == WM_FONTCHANGE )
4440         nSalEvent = SALEVENT_FONTCHANGED;
4441     else if ( nMsg == WM_TIMECHANGE )
4442         nSalEvent = SALEVENT_DATETIMECHANGED;
4443     else if ( nMsg == WM_WININICHANGE )
4444     {
4445         if ( lParam )
4446         {
4447                 if ( ImplSalWICompareAscii( (const wchar_t*)lParam, "devices" ) == 0 )
4448                     nSalEvent = SALEVENT_PRINTERCHANGED;
4449         }
4450     }
4451 
4452     if ( nMsg == WM_SETTINGCHANGE )
4453     {
4454         if ( wParam == SPI_SETWHEELSCROLLLINES )
4455             aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
4456         else if( wParam == SPI_SETWHEELSCROLLCHARS )
4457             aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars();
4458     }
4459 
4460     if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal )
4461         ImplUpdateSysColorEntries();
4462 
4463     ImplSalYieldMutexAcquireWithWait();
4464 
4465     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4466     if ( pFrame )
4467     {
4468         if ( (nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE) )
4469         {
4470             if ( pFrame->mbFullScreen )
4471                 ImplSalFrameFullScreenPos( pFrame );
4472         }
4473 
4474         pFrame->CallCallback( nSalEvent, 0 );
4475     }
4476 
4477     ImplSalYieldMutexRelease();
4478 }
4479 
4480 // -----------------------------------------------------------------------
4481 
4482 static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam )
4483 {
4484     ImplSalYieldMutexAcquireWithWait();
4485     WinSalFrame* pFrame = GetWindowPtr( hWnd );
4486     if ( pFrame )
4487     {
4488         pFrame->CallCallback( SALEVENT_USEREVENT, (void*)lParam );
4489     }
4490     ImplSalYieldMutexRelease();
4491 }
4492 
4493 // -----------------------------------------------------------------------
4494 
4495 static void ImplHandleForcePalette( HWND hWnd )
4496 {
4497     SalData*    pSalData = GetSalData();
4498     HPALETTE    hPal = pSalData->mhDitherPal;
4499     if ( hPal )
4500     {
4501         if ( !ImplSalYieldMutexTryToAcquire() )
4502         {
4503             ImplPostMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
4504             return;
4505         }
4506 
4507         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4508         if ( pFrame && pFrame->mpGraphics )
4509         {
4510             WinSalGraphics* pGraphics = pFrame->mpGraphics;
4511             if ( pGraphics && pGraphics->mhDefPal )
4512             {
4513                 SelectPalette( pGraphics->getHDC(), hPal, FALSE );
4514                 if ( RealizePalette( pGraphics->getHDC() ) )
4515                 {
4516                     InvalidateRect( hWnd, NULL, FALSE );
4517                     UpdateWindow( hWnd );
4518                     pFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
4519                 }
4520             }
4521         }
4522 
4523         ImplSalYieldMutexRelease();
4524     }
4525 }
4526 
4527 // -----------------------------------------------------------------------
4528 
4529 static LRESULT ImplHandlePalette( sal_Bool bFrame, HWND hWnd, UINT nMsg,
4530                                   WPARAM wParam, LPARAM lParam, int& rDef )
4531 {
4532     SalData*    pSalData = GetSalData();
4533     HPALETTE    hPal = pSalData->mhDitherPal;
4534     if ( !hPal )
4535         return 0;
4536 
4537     rDef = FALSE;
4538     if ( pSalData->mbInPalChange )
4539         return 0;
4540 
4541     if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
4542     {
4543         if ( (HWND)wParam == hWnd )
4544             return 0;
4545     }
4546 
4547     sal_Bool bReleaseMutex = FALSE;
4548     if ( (nMsg == WM_QUERYNEWPALETTE) || (nMsg == WM_PALETTECHANGED) )
4549     {
4550         // Da Windows diese Messages auch sendet, muss hier auch die
4551         // Solar-Semaphore beruecksichtigt werden
4552         if ( ImplSalYieldMutexTryToAcquire() )
4553             bReleaseMutex = TRUE;
4554         else if ( nMsg == WM_QUERYNEWPALETTE )
4555             ImplPostMessage( hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam );
4556         else /* ( nMsg == WM_PALETTECHANGED ) */
4557             ImplPostMessage( hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam );
4558     }
4559 
4560     WinSalVirtualDevice*pTempVD;
4561     WinSalFrame*        pTempFrame;
4562     WinSalGraphics*     pGraphics;
4563     HDC                 hDC;
4564     HPALETTE            hOldPal;
4565     UINT                nCols;
4566     sal_Bool                bStdDC;
4567     sal_Bool                bUpdate;
4568 
4569     pSalData->mbInPalChange = TRUE;
4570 
4571     // Alle Paletten in VirDevs und Frames zuruecksetzen
4572     pTempVD = pSalData->mpFirstVD;
4573     while ( pTempVD )
4574     {
4575         pGraphics = pTempVD->mpGraphics;
4576         if ( pGraphics->mhDefPal )
4577         {
4578             SelectPalette( pGraphics->getHDC(),
4579                            pGraphics->mhDefPal,
4580                            TRUE );
4581         }
4582         pTempVD = pTempVD->mpNext;
4583     }
4584     pTempFrame = pSalData->mpFirstFrame;
4585     while ( pTempFrame )
4586     {
4587         pGraphics = pTempFrame->mpGraphics;
4588         if ( pGraphics && pGraphics->mhDefPal )
4589         {
4590             SelectPalette( pGraphics->getHDC(),
4591                            pGraphics->mhDefPal,
4592                            TRUE );
4593         }
4594         pTempFrame = pTempFrame->mpNextFrame;
4595     }
4596 
4597     // Palette neu realizen
4598     WinSalFrame* pFrame = NULL;
4599     if ( bFrame )
4600         pFrame = GetWindowPtr( hWnd );
4601     if ( pFrame && pFrame->mpGraphics )
4602     {
4603         hDC = pFrame->mpGraphics->getHDC();
4604         bStdDC = TRUE;
4605     }
4606     else
4607     {
4608         hDC = GetDC( hWnd );
4609         bStdDC = FALSE;
4610     }
4611     UnrealizeObject( hPal );
4612     hOldPal = SelectPalette( hDC, hPal, TRUE );
4613     nCols = RealizePalette( hDC );
4614     bUpdate = nCols != 0;
4615     if ( !bStdDC )
4616     {
4617         SelectPalette( hDC, hOldPal, TRUE );
4618         ReleaseDC( hWnd, hDC );
4619     }
4620 
4621     // Alle Paletten in VirDevs und Frames neu setzen
4622     pTempVD = pSalData->mpFirstVD;
4623     while ( pTempVD )
4624     {
4625         pGraphics = pTempVD->mpGraphics;
4626         if ( pGraphics->mhDefPal )
4627         {
4628             SelectPalette( pGraphics->getHDC(), hPal, TRUE );
4629             RealizePalette( pGraphics->getHDC() );
4630         }
4631         pTempVD = pTempVD->mpNext;
4632     }
4633     pTempFrame = pSalData->mpFirstFrame;
4634     while ( pTempFrame )
4635     {
4636         if ( pTempFrame != pFrame )
4637         {
4638             pGraphics = pTempFrame->mpGraphics;
4639             if ( pGraphics && pGraphics->mhDefPal )
4640             {
4641                 SelectPalette( pGraphics->getHDC(), hPal, TRUE );
4642                 if ( RealizePalette( pGraphics->getHDC() ) )
4643                     bUpdate = TRUE;
4644             }
4645         }
4646         pTempFrame = pTempFrame->mpNextFrame;
4647     }
4648 
4649     // Wenn sich Farben geaendert haben, dann die Fenster updaten
4650     if ( bUpdate )
4651     {
4652         pTempFrame = pSalData->mpFirstFrame;
4653         while ( pTempFrame )
4654         {
4655             pGraphics = pTempFrame->mpGraphics;
4656             if ( pGraphics && pGraphics->mhDefPal )
4657             {
4658                 InvalidateRect( pTempFrame->mhWnd, NULL, FALSE );
4659                 UpdateWindow( pTempFrame->mhWnd );
4660                 pTempFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
4661             }
4662             pTempFrame = pTempFrame->mpNextFrame;
4663         }
4664     }
4665 
4666     pSalData->mbInPalChange = FALSE;
4667 
4668     if ( bReleaseMutex )
4669         ImplSalYieldMutexRelease();
4670 
4671     if ( nMsg == WM_PALETTECHANGED )
4672         return 0;
4673     else
4674         return nCols;
4675 }
4676 
4677 // -----------------------------------------------------------------------
4678 
4679 static int ImplHandleMinMax( HWND hWnd, LPARAM lParam )
4680 {
4681     int bRet = FALSE;
4682 
4683     if ( ImplSalYieldMutexTryToAcquire() )
4684     {
4685         WinSalFrame* pFrame = GetWindowPtr( hWnd );
4686         if ( pFrame )
4687         {
4688             MINMAXINFO* pMinMax = (MINMAXINFO*)lParam;
4689 
4690             if ( pFrame->mbFullScreen )
4691             {
4692                 int         nX;
4693                 int         nY;
4694                 int         nDX;
4695                 int         nDY;
4696                 ImplSalCalcFullScreenSize( pFrame, nX, nY, nDX, nDY );
4697 
4698                 if ( pMinMax->ptMaxPosition.x > nX )
4699                     pMinMax->ptMaxPosition.x = nX;
4700                 if ( pMinMax->ptMaxPosition.y > nY )
4701                     pMinMax->ptMaxPosition.y = nY;
4702 
4703                 if ( pMinMax->ptMaxSize.x < nDX )
4704                     pMinMax->ptMaxSize.x = nDX;
4705                 if ( pMinMax->ptMaxSize.y < nDY )
4706                     pMinMax->ptMaxSize.y = nDY;
4707                 if ( pMinMax->ptMaxTrackSize.x < nDX )
4708                     pMinMax->ptMaxTrackSize.x = nDX;
4709                 if ( pMinMax->ptMaxTrackSize.y < nDY )
4710                     pMinMax->ptMaxTrackSize.y = nDY;
4711 
4712                 pMinMax->ptMinTrackSize.x = nDX;
4713                 pMinMax->ptMinTrackSize.y = nDY;
4714 
4715                 bRet = TRUE;
4716             }
4717 
4718             if ( pFrame->mnMinWidth || pFrame->mnMinHeight )
4719             {
4720                 int nWidth   = pFrame->mnMinWidth;
4721                 int nHeight  = pFrame->mnMinHeight;
4722 
4723                 ImplSalAddBorder( pFrame, nWidth, nHeight );
4724 
4725                 if ( pMinMax->ptMinTrackSize.x < nWidth )
4726                      pMinMax->ptMinTrackSize.x = nWidth;
4727                 if ( pMinMax->ptMinTrackSize.y < nHeight )
4728                      pMinMax->ptMinTrackSize.y = nHeight;
4729             }
4730 
4731             if ( pFrame->mnMaxWidth || pFrame->mnMaxHeight )
4732             {
4733                 int nWidth   = pFrame->mnMaxWidth;
4734                 int nHeight  = pFrame->mnMaxHeight;
4735 
4736                 ImplSalAddBorder( pFrame, nWidth, nHeight );
4737 
4738                 if( nWidth > 0 && nHeight > 0 ) // protect against int overflow due to INT_MAX initialisation
4739                 {
4740                     if ( pMinMax->ptMaxTrackSize.x > nWidth )
4741                         pMinMax->ptMaxTrackSize.x = nWidth;
4742                     if ( pMinMax->ptMaxTrackSize.y > nHeight )
4743                         pMinMax->ptMaxTrackSize.y = nHeight;
4744                 }
4745             }
4746         }
4747 
4748         ImplSalYieldMutexRelease();
4749     }
4750 
4751     return bRet;
4752 }
4753 
4754 // -----------------------------------------------------------------------
4755 
4756 // retrieves the SalMenuItem pointer from a hMenu
4757 // the pointer is stored in every item, so if no position
4758 // is specified we just use the first item (ie, pos=0)
4759 // if bByPosition is FALSE then nPos denotes a menu id instead of a position
4760 static WinSalMenuItem* ImplGetSalMenuItem( HMENU hMenu, UINT nPos, sal_Bool bByPosition=TRUE )
4761 {
4762     DWORD err=0;
4763 
4764     MENUITEMINFOW mi;
4765     memset(&mi, 0, sizeof(mi));
4766     mi.cbSize = sizeof( mi );
4767     mi.fMask = MIIM_DATA;
4768     if( !GetMenuItemInfoW( hMenu, nPos, bByPosition, &mi) )
4769         err = GetLastError();
4770 
4771     return (WinSalMenuItem *) mi.dwItemData;
4772 }
4773 
4774 // returns the index of the currently selected item if any or -1
4775 static int ImplGetSelectedIndex( HMENU hMenu )
4776 {
4777     DWORD err=0;
4778 
4779     MENUITEMINFOW mi;
4780     memset(&mi, 0, sizeof(mi));
4781     mi.cbSize = sizeof( mi );
4782     mi.fMask = MIIM_STATE;
4783     int n = GetMenuItemCount( hMenu );
4784     if( n != -1 )
4785     {
4786         for(int i=0; i<n; i++ )
4787         {
4788             if( !GetMenuItemInfoW( hMenu, i, TRUE, &mi) )
4789                 err = GetLastError();
4790             else
4791             {
4792                 if( mi.fState & MFS_HILITE )
4793                     return i;
4794             }
4795         }
4796     }
4797     return -1;
4798 }
4799 
4800 static int ImplMenuChar( HWND, WPARAM wParam, LPARAM lParam )
4801 {
4802     int nRet = MNC_IGNORE;
4803     HMENU hMenu = (HMENU) lParam;
4804     String aMnemonic;
4805     aMnemonic.AssignAscii("&");
4806     aMnemonic.Append( (sal_Unicode) LOWORD(wParam) );
4807     aMnemonic.ToLowerAscii();   // we only have ascii mnemonics
4808 
4809     // search the mnemonic in the current menu
4810     int nItemCount = GetMenuItemCount( hMenu );
4811     int nFound = 0;
4812     int idxFound = -1;
4813     int idxSelected = ImplGetSelectedIndex( hMenu );
4814     int idx = idxSelected != -1 ? idxSelected+1 : 0;    // if duplicate mnemonics cycle through menu
4815     for( int i=0; i< nItemCount; i++, idx++ )
4816     {
4817         WinSalMenuItem* pSalMenuItem = ImplGetSalMenuItem( hMenu, idx % nItemCount );
4818         if( !pSalMenuItem )
4819             continue;
4820         String aStr = pSalMenuItem->mText;
4821         aStr.ToLowerAscii();
4822         if( aStr.Search( aMnemonic ) != STRING_NOTFOUND)
4823         {
4824             if( idxFound == -1 )
4825                 idxFound = idx % nItemCount;
4826             if( nFound++ )
4827                 break;  // duplicate found
4828         }
4829     }
4830     if( nFound == 1 )
4831         nRet = MAKELRESULT( idxFound, MNC_EXECUTE );
4832     else
4833         // duplicate mnemonics, just select the next occurence
4834         nRet = MAKELRESULT( idxFound, MNC_SELECT );
4835 
4836     return nRet;
4837 }
4838 
4839 static int ImplMeasureItem( HWND hWnd, WPARAM wParam, LPARAM lParam )
4840 {
4841     int nRet = 0;
4842     if( !wParam )
4843     {
4844         // request was sent by a menu
4845         nRet = 1;
4846         MEASUREITEMSTRUCT *pMI = (LPMEASUREITEMSTRUCT) lParam;
4847         if( pMI->CtlType != ODT_MENU )
4848             return 0;
4849 
4850         WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pMI->itemData;
4851         if( !pSalMenuItem )
4852             return 0;
4853 
4854         HDC hdc = GetDC( hWnd );
4855         SIZE strSize;
4856 
4857         NONCLIENTMETRICS ncm;
4858         memset( &ncm, 0, sizeof(ncm) );
4859         ncm.cbSize = sizeof( ncm );
4860         SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 );
4861 
4862         // Assume every menu item can be default and printed bold
4863         //ncm.lfMenuFont.lfWeight = FW_BOLD;
4864 
4865         HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
4866 
4867         // menu text and accelerator
4868         String aStr(pSalMenuItem->mText.GetBuffer() );
4869         if( pSalMenuItem->mAccelText.Len() )
4870         {
4871             aStr.AppendAscii(" ");
4872             aStr.Append( pSalMenuItem->mAccelText );
4873         }
4874         GetTextExtentPoint32W( hdc, (LPWSTR) aStr.GetBuffer(),
4875                                 aStr.Len(), &strSize );
4876 
4877         // image
4878         Size bmpSize( 16, 16 );
4879         //if( !!pSalMenuItem->maBitmap )
4880         //    bmpSize = pSalMenuItem->maBitmap.GetSizePixel();
4881 
4882         // checkmark
4883         Size checkSize( GetSystemMetrics( SM_CXMENUCHECK ), GetSystemMetrics( SM_CYMENUCHECK ) );
4884 
4885         pMI->itemWidth = checkSize.Width() + 3 + bmpSize.Width() + 3 + strSize.cx;
4886         pMI->itemHeight = Max( Max( checkSize.Height(), bmpSize.Height() ), strSize.cy );
4887         pMI->itemHeight += 4;
4888 
4889         DeleteObject( SelectObject(hdc, hfntOld) );
4890         ReleaseDC( hWnd, hdc );
4891     }
4892 
4893     return nRet;
4894 }
4895 
4896 static int ImplDrawItem(HWND, WPARAM wParam, LPARAM lParam )
4897 {
4898     int nRet = 0;
4899     DWORD err = 0;
4900     if( !wParam )
4901     {
4902         // request was sent by a menu
4903         nRet = 1;
4904         DRAWITEMSTRUCT *pDI = (LPDRAWITEMSTRUCT) lParam;
4905         if( pDI->CtlType != ODT_MENU )
4906             return 0;
4907 
4908         WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pDI->itemData;
4909         if( !pSalMenuItem )
4910             return 0;
4911 
4912         COLORREF clrPrevText, clrPrevBkgnd;
4913         HFONT hfntOld;
4914         HBRUSH hbrOld;
4915         sal_Bool	fChecked = (pDI->itemState & ODS_CHECKED) ? TRUE : FALSE;
4916         sal_Bool	fSelected = (pDI->itemState & ODS_SELECTED) ? TRUE : FALSE;
4917         sal_Bool	fDisabled = (pDI->itemState & (ODS_DISABLED | ODS_GRAYED)) ? TRUE : FALSE;
4918 
4919         // Set the appropriate foreground and background colors.
4920         RECT aRect = pDI->rcItem;
4921 
4922         clrPrevBkgnd = SetBkColor( pDI->hDC, GetSysColor( COLOR_MENU ) );
4923 
4924         if ( fDisabled )
4925             clrPrevText = SetTextColor( pDI->hDC, GetSysColor( COLOR_GRAYTEXT ) );
4926         else
4927             clrPrevText = SetTextColor( pDI->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
4928 
4929         DWORD colBackground = GetSysColor( fSelected ? COLOR_HIGHLIGHT : COLOR_MENU );
4930         if ( fSelected )
4931 	        clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground );
4932         else
4933 	        clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground );
4934 
4935         hbrOld = (HBRUSH)SelectObject( pDI->hDC, CreateSolidBrush( GetBkColor( pDI->hDC ) ) );
4936 
4937         // Fill background
4938         if(!PatBlt( pDI->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY ))
4939             err = GetLastError();
4940 
4941         int lineHeight = aRect.bottom-aRect.top;
4942 
4943         int x = aRect.left;
4944         int y = aRect.top;
4945 
4946         int checkWidth  = GetSystemMetrics( SM_CXMENUCHECK );
4947         int checkHeight = GetSystemMetrics( SM_CYMENUCHECK );
4948         if( fChecked )
4949         {
4950             RECT r;
4951             r.left = 0;
4952             r.top = 0;
4953             r.right = checkWidth;
4954             r.bottom = checkWidth;
4955             HDC memDC = CreateCompatibleDC( pDI->hDC );
4956             HBITMAP memBmp = CreateCompatibleBitmap( pDI->hDC, checkWidth, checkHeight );
4957             HBITMAP hOldBmp = (HBITMAP) SelectObject( memDC, memBmp );
4958             DrawFrameControl( memDC, &r, DFC_MENU, DFCS_MENUCHECK );
4959             BitBlt( pDI->hDC, x, y+(lineHeight-checkHeight)/2, checkWidth, checkHeight, memDC, 0, 0, SRCAND );
4960             DeleteObject( SelectObject( memDC, hOldBmp ) );
4961             DeleteDC( memDC );
4962         }
4963         x += checkWidth+3;
4964 
4965         //Size bmpSize = aBitmap.GetSizePixel();
4966         Size bmpSize(16, 16);
4967         if( !!pSalMenuItem->maBitmap )
4968         {
4969             Bitmap aBitmap( pSalMenuItem->maBitmap );
4970 
4971             // set transparent pixels to background color
4972             if( fDisabled )
4973                 colBackground = RGB(255,255,255);
4974             aBitmap.Replace( Color( COL_LIGHTMAGENTA ),
4975                 Color( GetRValue(colBackground),GetGValue(colBackground),GetBValue(colBackground) ), 0);
4976 
4977             WinSalBitmap* pSalBmp = static_cast<WinSalBitmap*>(aBitmap.ImplGetImpBitmap()->ImplGetSalBitmap());
4978 			HGLOBAL hDrawDIB = pSalBmp->ImplGethDIB();
4979 
4980             if( hDrawDIB )
4981             {
4982                 PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( hDrawDIB );
4983 			    PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
4984 			    PBYTE				pBits = (PBYTE) pBI + *(DWORD*) pBI +
4985 										    pSalBmp->ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD );
4986 
4987                 HBITMAP hBmp = CreateDIBitmap( pDI->hDC, pBIH, CBM_INIT, pBits, pBI, DIB_RGB_COLORS );
4988 			    GlobalUnlock( hDrawDIB );
4989 
4990                 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
4991                 DrawStateW( pDI->hDC, (HBRUSH)hbrIcon, (DRAWSTATEPROC)NULL, (LPARAM)hBmp, (WPARAM)0,
4992                     x, y+(lineHeight-bmpSize.Height())/2, bmpSize.Width(), bmpSize.Height(),
4993                      DST_BITMAP | (fDisabled ? (fSelected ? DSS_MONO : DSS_DISABLED) : DSS_NORMAL) );
4994 
4995                 DeleteObject( hbrIcon );
4996                 DeleteObject( hBmp );
4997             }
4998 
4999         }
5000         x += bmpSize.Width() + 3;
5001         aRect.left = x;
5002 
5003         NONCLIENTMETRICS ncm;
5004         memset( &ncm, 0, sizeof(ncm) );
5005         ncm.cbSize = sizeof( ncm );
5006         SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 );
5007 
5008         // Print default menu entry with bold font
5009         //if ( pDI->itemState & ODS_DEFAULT )
5010 	    //    ncm.lfMenuFont.lfWeight = FW_BOLD;
5011 
5012         hfntOld = (HFONT) SelectObject(pDI->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
5013 
5014         SIZE strSize;
5015         String aStr( pSalMenuItem->mText.GetBuffer() );
5016         GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(),
5017                                 aStr.Len(), &strSize );
5018 
5019         if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL,
5020             (LPARAM)(LPWSTR) aStr.GetBuffer(),
5021             (WPARAM)0, aRect.left, aRect.top + (lineHeight - strSize.cy)/2, 0, 0,
5022             DST_PREFIXTEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) )
5023             err = GetLastError();
5024 
5025         if( pSalMenuItem->mAccelText.Len() )
5026         {
5027             SIZE strSizeA;
5028             aStr = pSalMenuItem->mAccelText;
5029             GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(),
5030                                     aStr.Len(), &strSizeA );
5031             TEXTMETRIC tm;
5032             GetTextMetrics( pDI->hDC, &tm );
5033 
5034             // position the accelerator string to the right but leave space for the
5035             // (potential) submenu arrow (tm.tmMaxCharWidth)
5036             if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL,
5037                 (LPARAM)(LPWSTR) aStr.GetBuffer(),
5038                 (WPARAM)0, aRect.right-strSizeA.cx-tm.tmMaxCharWidth, aRect.top + (lineHeight - strSizeA.cy)/2, 0, 0,
5039                 DST_TEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) )
5040                 err = GetLastError();
5041         }
5042 
5043         // Restore the original font and colors.
5044         DeleteObject( SelectObject( pDI->hDC, hbrOld ) );
5045         DeleteObject( SelectObject( pDI->hDC, hfntOld) );
5046         SetTextColor(pDI->hDC, clrPrevText);
5047         SetBkColor(pDI->hDC, clrPrevBkgnd);
5048     }
5049     return nRet;
5050 }
5051 
5052 static int ImplHandleMenuActivate( HWND hWnd, WPARAM wParam, LPARAM )
5053 {
5054     // Menu activation
5055     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5056     if ( !pFrame )
5057         return 0;
5058 
5059     HMENU hMenu = (HMENU) wParam;
5060     // WORD nPos = LOWORD (lParam);
5061     // sal_Bool bWindowMenu = (sal_Bool) HIWORD(lParam);
5062 
5063     // Send activate and deactivate together, so we have not keep track of opened menues
5064     // this will be enough to have the menues updated correctly
5065     SalMenuEvent aMenuEvt;
5066     WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, 0 );
5067     if( pSalMenuItem )
5068         aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5069     else
5070         aMenuEvt.mpMenu = NULL;
5071 
5072     long nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt );
5073     if( nRet )
5074         nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt );
5075     if( nRet )
5076         pFrame->mLastActivatedhMenu = hMenu;
5077 
5078     return (nRet!=0);
5079 }
5080 
5081 static int ImplHandleMenuSelect( HWND hWnd, WPARAM wParam, LPARAM lParam )
5082 {
5083     // Menu selection
5084     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5085     if ( !pFrame )
5086         return 0;
5087 
5088     WORD nId = LOWORD(wParam);      // menu item or submenu index
5089     WORD nFlags = HIWORD(wParam);
5090     HMENU hMenu = (HMENU) lParam;
5091 
5092     // check if we have to process the message
5093     if( !GetSalData()->IsKnownMenuHandle( hMenu ) )
5094         return 0;
5095 
5096     sal_Bool bByPosition = FALSE;
5097     if( nFlags & MF_POPUP )
5098         bByPosition = TRUE;
5099 
5100     long nRet = 0;
5101     if ( hMenu && !pFrame->mLastActivatedhMenu )
5102     {
5103         // we never activated a menu (ie, no WM_INITMENUPOPUP has occured yet)
5104         // which means this must be the menubar -> send activation/deactivation
5105         SalMenuEvent aMenuEvt;
5106         WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, bByPosition );
5107         if( pSalMenuItem )
5108             aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5109         else
5110             aMenuEvt.mpMenu = NULL;
5111 
5112         nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt );
5113         if( nRet )
5114             nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt );
5115         if( nRet )
5116             pFrame->mLastActivatedhMenu = hMenu;
5117     }
5118 
5119     if( !hMenu && nFlags == 0xFFFF )
5120     {
5121         // all menus are closed, reset activation logic
5122         pFrame->mLastActivatedhMenu = NULL;
5123     }
5124 
5125     if( hMenu )
5126     {
5127         // hMenu must be saved, as it is not passed in WM_COMMAND which always occurs after a selection
5128         // if a menu is closed due to a command selection then hMenu is NULL, but WM_COMMAND comes later
5129         // so we must not overwrite it in this case
5130         pFrame->mSelectedhMenu = hMenu;
5131 
5132         // send highlight event
5133         if( nFlags & MF_POPUP )
5134         {
5135             // submenu selected
5136             // wParam now carries an index instead of an id -> retrieve id
5137             MENUITEMINFOW mi;
5138             memset(&mi, 0, sizeof(mi));
5139             mi.cbSize = sizeof( mi );
5140             mi.fMask = MIIM_ID;
5141             if( GetMenuItemInfoW( hMenu, LOWORD(wParam), TRUE, &mi) )
5142                 nId = sal::static_int_cast<WORD>(mi.wID);
5143         }
5144 
5145         SalMenuEvent aMenuEvt;
5146         aMenuEvt.mnId   = nId;
5147         WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, FALSE );
5148         if( pSalMenuItem )
5149             aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5150         else
5151             aMenuEvt.mpMenu = NULL;
5152 
5153         nRet = pFrame->CallCallback( SALEVENT_MENUHIGHLIGHT, &aMenuEvt );
5154     }
5155 
5156     return (nRet != 0);
5157 }
5158 
5159 static int ImplHandleCommand( HWND hWnd, WPARAM wParam, LPARAM )
5160 {
5161     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5162     if ( !pFrame )
5163         return 0;
5164 
5165     long nRet = 0;
5166     if( !HIWORD(wParam) )
5167     {
5168         // Menu command
5169         WORD nId = LOWORD(wParam);
5170         if( nId )   // zero for separators
5171         {
5172             SalMenuEvent aMenuEvt;
5173             aMenuEvt.mnId   = nId;
5174             WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( pFrame->mSelectedhMenu, nId, FALSE );
5175             if( pSalMenuItem )
5176                 aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
5177             else
5178                 aMenuEvt.mpMenu = NULL;
5179 
5180             nRet = pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt );
5181         }
5182     }
5183     return (nRet != 0);
5184 }
5185 
5186 static int ImplHandleSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
5187 {
5188     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5189     if ( !pFrame )
5190         return 0;
5191 
5192     WPARAM nCommand = wParam & 0xFFF0;
5193 
5194     if ( pFrame->mbFullScreen )
5195     {
5196         BOOL    bMaximize = IsZoomed( pFrame->mhWnd );
5197         BOOL    bMinimize = IsIconic( pFrame->mhWnd );
5198         if ( (nCommand == SC_SIZE) ||
5199              (!bMinimize && (nCommand == SC_MOVE)) ||
5200              (!bMaximize && (nCommand == SC_MAXIMIZE)) ||
5201              (bMaximize && (nCommand == SC_RESTORE)) )
5202         {
5203             MessageBeep( 0 );
5204             return TRUE;
5205         }
5206     }
5207 
5208     if ( nCommand == SC_KEYMENU )
5209     {
5210         // do not process SC_KEYMENU if we have a native menu
5211         // Windows should handle this
5212         if( GetMenu( hWnd ) )
5213             return FALSE;
5214 
5215         // Hier verarbeiten wir nur KeyMenu-Events fuer Alt um
5216         // den MenuBar zu aktivieren, oder wenn ein SysChild-Fenster
5217         // den Focus hat, da diese Alt+Tasten-Kombinationen nur
5218         // ueber diesen Event verarbeitet werden
5219         if ( !LOWORD( lParam ) )
5220         {
5221             // Nur ausloesen, wenn keine weitere Taste gedrueckt ist. Im
5222             // Gegensatz zur Doku wird in der X-Koordinaate der CharCode
5223             // geliefert, der zusaetzlich gedrueckt ist
5224             // Also 32 fuer Space, 99 fuer c, 100 fuer d, ...
5225             // Da dies nicht dokumentiert ist, fragen wir vorsichtshalber
5226             // auch den Status der Space-Taste ab
5227             if ( GetKeyState( VK_SPACE ) & 0x8000 )
5228                 return 0;
5229 
5230             // Damit nicht bei Alt+Maustaste auch der MenuBar aktiviert wird
5231             if ( (GetKeyState( VK_LBUTTON ) & 0x8000) ||
5232                  (GetKeyState( VK_RBUTTON ) & 0x8000) ||
5233                  (GetKeyState( VK_MBUTTON ) & 0x8000) ||
5234 				 (GetKeyState( VK_SHIFT )   & 0x8000) )
5235                 return 1;
5236 
5237             SalKeyEvent aKeyEvt;
5238             aKeyEvt.mnTime      = GetMessageTime();
5239             aKeyEvt.mnCode      = KEY_MENU;
5240             aKeyEvt.mnCharCode  = 0;
5241             aKeyEvt.mnRepeat    = 0;
5242             long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
5243             pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
5244             return (nRet != 0);
5245         }
5246         else
5247         {
5248             // Testen, ob ein SysChild den Focus hat
5249             HWND hFocusWnd = ::GetFocus();
5250             if ( hFocusWnd && ImplFindSalObject( hFocusWnd ) )
5251             {
5252                 char cKeyCode = (char)(unsigned char)LOWORD( lParam );
5253                 // LowerCase
5254                 if ( (cKeyCode >= 65) && (cKeyCode <= 90) )
5255                     cKeyCode += 32;
5256                 // Wir nehmen nur 0-9 und A-Z, alle anderen Tasten muessen durch
5257                 // den Hook vom SalObj verarbeitet werden
5258                 if ( ((cKeyCode >= 48) && (cKeyCode <= 57)) ||
5259                      ((cKeyCode >= 97) && (cKeyCode <= 122)) )
5260                 {
5261                     sal_uInt16 nModCode = 0;
5262                     if ( GetKeyState( VK_SHIFT ) & 0x8000 )
5263                         nModCode |= KEY_SHIFT;
5264                     if ( GetKeyState( VK_CONTROL ) & 0x8000 )
5265                         nModCode |= KEY_MOD1;
5266                     nModCode |= KEY_MOD2;
5267 
5268                     SalKeyEvent aKeyEvt;
5269                     aKeyEvt.mnTime      = GetMessageTime();
5270                     if ( (cKeyCode >= 48) && (cKeyCode <= 57) )
5271                         aKeyEvt.mnCode = KEY_0+(cKeyCode-48);
5272                     else
5273                         aKeyEvt.mnCode = KEY_A+(cKeyCode-97);
5274                     aKeyEvt.mnCode     |= nModCode;
5275                     aKeyEvt.mnCharCode  = cKeyCode;
5276                     aKeyEvt.mnRepeat    = 0;
5277                     long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
5278                     pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt );
5279                     return (nRet != 0);
5280                 }
5281             }
5282         }
5283     }
5284 
5285     return FALSE;
5286 }
5287 
5288 // -----------------------------------------------------------------------
5289 
5290 static void ImplHandleInputLangChange( HWND hWnd, WPARAM, LPARAM lParam )
5291 {
5292     ImplSalYieldMutexAcquireWithWait();
5293 
5294     // Feststellen, ob wir IME unterstuetzen
5295     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5296     if ( pFrame && pFrame->mbIME && pFrame->mhDefIMEContext )
5297     {
5298         HKL     hKL = (HKL)lParam;
5299         UINT    nImeProps = ImmGetProperty( hKL, IGP_PROPERTY );
5300 
5301         pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
5302         pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
5303         pFrame->mbHandleIME = !pFrame->mbSpezIME;
5304     }
5305 
5306     // trigger input language and codepage update
5307     UINT nLang = pFrame->mnInputLang;
5308     ImplUpdateInputLang( pFrame );
5309 
5310     // notify change
5311     if( nLang != pFrame->mnInputLang )
5312         pFrame->CallCallback( SALEVENT_INPUTLANGUAGECHANGE, 0 );
5313 
5314     ImplSalYieldMutexRelease();
5315 }
5316 
5317 // -----------------------------------------------------------------------
5318 
5319 static void ImplUpdateIMECursorPos( WinSalFrame* pFrame, HIMC hIMC )
5320 {
5321     COMPOSITIONFORM aForm;
5322     memset( &aForm, 0, sizeof( aForm ) );
5323 
5324     // Cursor-Position ermitteln und aus der die Default-Position fuer
5325     // das Composition-Fenster berechnen
5326     SalExtTextInputPosEvent aPosEvt;
5327     pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
5328     if ( (aPosEvt.mnX == -1) && (aPosEvt.mnY == -1) )
5329         aForm.dwStyle |= CFS_DEFAULT;
5330     else
5331     {
5332         aForm.dwStyle          |= CFS_POINT;
5333         aForm.ptCurrentPos.x    = aPosEvt.mnX;
5334         aForm.ptCurrentPos.y    = aPosEvt.mnY;
5335     }
5336     ImmSetCompositionWindow( hIMC, &aForm );
5337 
5338     // Because not all IME's use this values, we create
5339     // a Windows caret to force the Position from the IME
5340     if ( GetFocus() == pFrame->mhWnd )
5341     {
5342         CreateCaret( pFrame->mhWnd, 0,
5343                      aPosEvt.mnWidth, aPosEvt.mnHeight );
5344         SetCaretPos( aPosEvt.mnX, aPosEvt.mnY );
5345     }
5346 }
5347 
5348 // -----------------------------------------------------------------------
5349 
5350 static sal_Bool ImplHandleIMEStartComposition( HWND hWnd )
5351 {
5352     sal_Bool bDef = TRUE;
5353 
5354     ImplSalYieldMutexAcquireWithWait();
5355 
5356     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5357     if ( pFrame )
5358     {
5359         HIMC hIMC = ImmGetContext( hWnd );
5360         if ( hIMC )
5361         {
5362             ImplUpdateIMECursorPos( pFrame, hIMC );
5363             ImmReleaseContext( hWnd, hIMC );
5364         }
5365 
5366         if ( pFrame->mbHandleIME )
5367         {
5368             if ( pFrame->mbAtCursorIME )
5369                 bDef = FALSE;
5370         }
5371     }
5372 
5373     ImplSalYieldMutexRelease();
5374 
5375     return bDef;
5376 }
5377 
5378 // -----------------------------------------------------------------------
5379 
5380 static sal_Bool ImplHandleIMECompositionInput( WinSalFrame* pFrame,
5381                                            HIMC hIMC, LPARAM lParam )
5382 {
5383     sal_Bool bDef = TRUE;
5384 
5385     // Init Event
5386     SalExtTextInputEvent    aEvt;
5387     aEvt.mnTime             = GetMessageTime();
5388     aEvt.mpTextAttr         = NULL;
5389     aEvt.mnCursorPos        = 0;
5390     aEvt.mnDeltaStart       = 0;
5391     aEvt.mbOnlyCursor       = FALSE;
5392     aEvt.mnCursorFlags      = 0;
5393 
5394     // If we get a result string, then we handle this input
5395     if ( lParam & GCS_RESULTSTR )
5396     {
5397         bDef = FALSE;
5398 
5399         LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, 0, 0 ) / sizeof( WCHAR );
5400         if ( nTextLen >= 0 )
5401         {
5402             WCHAR* pTextBuf = new WCHAR[nTextLen];
5403             ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
5404             aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen );
5405             delete [] pTextBuf;
5406         }
5407 
5408         aEvt.mnCursorPos = aEvt.maText.Len();
5409         pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5410         pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5411         ImplUpdateIMECursorPos( pFrame, hIMC );
5412     }
5413 
5414     // If the IME doesn't support OnSpot input, then there is nothing to do
5415     if ( !pFrame->mbAtCursorIME )
5416         return !bDef;
5417 
5418     // If we get new Composition data, then we handle this new input
5419     if ( (lParam & (GCS_COMPSTR | GCS_COMPATTR)) ||
5420          ((lParam & GCS_CURSORPOS) && !(lParam & GCS_RESULTSTR)) )
5421     {
5422         bDef = FALSE;
5423 
5424         sal_uInt16* pSalAttrAry = NULL;
5425         LONG    nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ) / sizeof( WCHAR );
5426         if ( nTextLen > 0 )
5427         {
5428             WCHAR* pTextBuf = new WCHAR[nTextLen];
5429             ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf, nTextLen*sizeof( WCHAR ) );
5430             aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen );
5431             delete [] pTextBuf;
5432 
5433             BYTE*   pAttrBuf = NULL;
5434             LONG        nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, 0, 0 );
5435             if ( nAttrLen > 0 )
5436             {
5437                 pAttrBuf = new BYTE[nAttrLen];
5438                 ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf, nAttrLen );
5439             }
5440 
5441             if ( pAttrBuf )
5442             {
5443                 xub_StrLen nTextLen = aEvt.maText.Len();
5444                 pSalAttrAry = new sal_uInt16[nTextLen];
5445                 memset( pSalAttrAry, 0, nTextLen*sizeof( sal_uInt16 ) );
5446                 for ( xub_StrLen i = 0; (i < nTextLen) && (i < nAttrLen); i++ )
5447                 {
5448                     BYTE nWinAttr = pAttrBuf[i];
5449                     sal_uInt16   nSalAttr;
5450                     if ( nWinAttr == ATTR_TARGET_CONVERTED )
5451                     {
5452                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
5453                         aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
5454                     }
5455                     else if ( nWinAttr == ATTR_CONVERTED )
5456                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE;
5457                     else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED )
5458                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
5459                     else if ( nWinAttr == ATTR_INPUT_ERROR )
5460                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
5461                     else /* ( nWinAttr == ATTR_INPUT ) */
5462                         nSalAttr = SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
5463                     pSalAttrAry[i] = nSalAttr;
5464                 }
5465 
5466                 aEvt.mpTextAttr = pSalAttrAry;
5467                 delete [] pAttrBuf;
5468             }
5469         }
5470 
5471         // Only when we get new composition data, we must send this event
5472         if ( (nTextLen > 0) || !(lParam & GCS_RESULTSTR) )
5473         {
5474             // End the mode, if the last character is deleted
5475             if ( !nTextLen && !pFrame->mbCandidateMode )
5476             {
5477                 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5478                 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5479             }
5480             else
5481             {
5482                 // Because Cursor-Position and DeltaStart never updated
5483                 // from the korean input engine, we must handle this here
5484                 if ( lParam & CS_INSERTCHAR )
5485                 {
5486                     aEvt.mnCursorPos = nTextLen;
5487                     if ( aEvt.mnCursorPos && (lParam & CS_NOMOVECARET) )
5488                         aEvt.mnCursorPos--;
5489                 }
5490                 else
5491                     aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, 0, 0 ) );
5492 
5493                 if ( pFrame->mbCandidateMode )
5494                     aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE;
5495                 if ( lParam & CS_NOMOVECARET )
5496                     aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_OVERWRITE;
5497 
5498                 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5499             }
5500             ImplUpdateIMECursorPos( pFrame, hIMC );
5501         }
5502 
5503         if ( pSalAttrAry )
5504             delete [] pSalAttrAry;
5505     }
5506 
5507     return !bDef;
5508 }
5509 
5510 // -----------------------------------------------------------------------
5511 
5512 static sal_Bool ImplHandleIMEComposition( HWND hWnd, LPARAM lParam )
5513 {
5514     sal_Bool bDef = TRUE;
5515     ImplSalYieldMutexAcquireWithWait();
5516 
5517     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5518     if ( pFrame && (!lParam || (lParam & GCS_RESULTSTR)) )
5519     {
5520         // Wir restaurieren den Background-Modus bei jeder Texteingabe,
5521         // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen
5522         if ( pFrame->mpGraphics &&
5523              pFrame->mpGraphics->getHDC() )
5524             SetBkMode( pFrame->mpGraphics->getHDC(), TRANSPARENT );
5525     }
5526 
5527     if ( pFrame && pFrame->mbHandleIME )
5528     {
5529         if ( !lParam )
5530         {
5531             SalExtTextInputEvent aEvt;
5532             aEvt.mnTime             = GetMessageTime();
5533             aEvt.mpTextAttr         = NULL;
5534             aEvt.mnCursorPos        = 0;
5535             aEvt.mnDeltaStart       = 0;
5536             aEvt.mbOnlyCursor       = FALSE;
5537             aEvt.mnCursorFlags      = 0;
5538             pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
5539             pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
5540         }
5541         else if ( lParam & (GCS_RESULTSTR | GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) )
5542         {
5543             HIMC hIMC = ImmGetContext( hWnd );
5544             if ( hIMC )
5545             {
5546                 if ( ImplHandleIMECompositionInput( pFrame, hIMC, lParam ) )
5547                     bDef = FALSE;
5548 
5549                 ImmReleaseContext( hWnd, hIMC );
5550             }
5551         }
5552     }
5553 
5554     ImplSalYieldMutexRelease();
5555     return bDef;
5556 }
5557 
5558 // -----------------------------------------------------------------------
5559 
5560 static sal_Bool ImplHandleIMEEndComposition( HWND hWnd )
5561 {
5562     sal_Bool bDef = TRUE;
5563 
5564     ImplSalYieldMutexAcquireWithWait();
5565 
5566     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5567     if ( pFrame && pFrame->mbHandleIME )
5568     {
5569         if ( pFrame->mbAtCursorIME )
5570             bDef = FALSE;
5571     }
5572 
5573     ImplSalYieldMutexRelease();
5574 
5575     return bDef;
5576 }
5577 
5578 // -----------------------------------------------------------------------
5579 
5580 static boolean ImplHandleAppCommand( HWND hWnd, LPARAM lParam )
5581 {
5582 	sal_Int16 nCommand = 0;
5583 	switch( GET_APPCOMMAND_LPARAM(lParam) )
5584 	{
5585 	case APPCOMMAND_MEDIA_CHANNEL_DOWN:			nCommand = MEDIA_COMMAND_CHANNEL_DOWN; break;
5586 	case APPCOMMAND_MEDIA_CHANNEL_UP:			nCommand = MEDIA_COMMAND_CHANNEL_UP; break;
5587 	case APPCOMMAND_MEDIA_NEXTTRACK:			nCommand = MEDIA_COMMAND_NEXTTRACK; break;
5588 	case APPCOMMAND_MEDIA_PAUSE:				nCommand = MEDIA_COMMAND_PAUSE; break;
5589 	case APPCOMMAND_MEDIA_PLAY:					nCommand = MEDIA_COMMAND_PLAY; break;
5590 	case APPCOMMAND_MEDIA_PLAY_PAUSE:			nCommand = MEDIA_COMMAND_PLAY_PAUSE; break;
5591 	case APPCOMMAND_MEDIA_PREVIOUSTRACK:		nCommand = MEDIA_COMMAND_PREVIOUSTRACK; break;
5592 	case APPCOMMAND_MEDIA_RECORD:				nCommand = MEDIA_COMMAND_RECORD; break;
5593 	case APPCOMMAND_MEDIA_REWIND:				nCommand = MEDIA_COMMAND_REWIND; break;
5594 	case APPCOMMAND_MEDIA_STOP:					nCommand = MEDIA_COMMAND_STOP; break;
5595 	case APPCOMMAND_MIC_ON_OFF_TOGGLE:			nCommand = MEDIA_COMMAND_MIC_ON_OFF_TOGGLE; break;
5596 	case APPCOMMAND_MICROPHONE_VOLUME_DOWN:		nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_DOWN; break;
5597 	case APPCOMMAND_MICROPHONE_VOLUME_MUTE:		nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_MUTE; break;
5598 	case APPCOMMAND_MICROPHONE_VOLUME_UP:		nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_UP; break;
5599 	case APPCOMMAND_VOLUME_DOWN:				nCommand = MEDIA_COMMAND_VOLUME_DOWN; break;
5600 	case APPCOMMAND_VOLUME_MUTE:				nCommand = MEDIA_COMMAND_VOLUME_MUTE; break;
5601 	case APPCOMMAND_VOLUME_UP:					nCommand = MEDIA_COMMAND_VOLUME_UP; break;
5602 		break;
5603 	default:
5604 		return false;
5605 	}
5606 
5607     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5608 	Window *pWindow = pFrame ? pFrame->GetWindow() : NULL;
5609 
5610 	if( pWindow )
5611 	{
5612 		const Point aPoint;
5613 		CommandEvent aCEvt( aPoint, COMMAND_MEDIA, FALSE, &nCommand );
5614 		NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt );
5615 
5616 		if ( !ImplCallPreNotify( aNCmdEvt ) )
5617         {
5618 			pWindow->Command( aCEvt );
5619             return true;
5620         }
5621 	}
5622 
5623     return false;
5624 }
5625 
5626 
5627 static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam )
5628 {
5629     if ( wParam == (WPARAM)IMN_OPENCANDIDATE )
5630     {
5631         ImplSalYieldMutexAcquireWithWait();
5632 
5633         WinSalFrame* pFrame = GetWindowPtr( hWnd );
5634         if ( pFrame && pFrame->mbHandleIME &&
5635              pFrame->mbAtCursorIME )
5636         {
5637             // Wir wollen den Cursor hiden
5638             pFrame->mbCandidateMode = TRUE;
5639             ImplHandleIMEComposition( hWnd, GCS_CURSORPOS );
5640 
5641             HWND hWnd = pFrame->mhWnd;
5642             HIMC hIMC = ImmGetContext( hWnd );
5643             if ( hIMC )
5644             {
5645                 LONG nBufLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 );
5646                 if ( nBufLen >= 1 )
5647                 {
5648                     SalExtTextInputPosEvent aPosEvt;
5649                     pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt );
5650 
5651                     // Vertical !!!
5652                     CANDIDATEFORM aForm;
5653                     aForm.dwIndex           = 0;
5654                     aForm.dwStyle           = CFS_EXCLUDE;
5655                     aForm.ptCurrentPos.x    = aPosEvt.mnX;
5656                     aForm.ptCurrentPos.y    = aPosEvt.mnY+1;
5657                     aForm.rcArea.left       = aPosEvt.mnX;
5658                     aForm.rcArea.top        = aPosEvt.mnY;
5659                     aForm.rcArea.right      = aForm.rcArea.left+aPosEvt.mnExtWidth+1;
5660                     aForm.rcArea.bottom     = aForm.rcArea.top+aPosEvt.mnHeight+1;
5661                     ImmSetCandidateWindow( hIMC, &aForm );
5662                 }
5663 
5664                 ImmReleaseContext( hWnd, hIMC );
5665             }
5666         }
5667 
5668         ImplSalYieldMutexRelease();
5669     }
5670     else if ( wParam == (WPARAM)IMN_CLOSECANDIDATE )
5671     {
5672         ImplSalYieldMutexAcquireWithWait();
5673         WinSalFrame* pFrame = GetWindowPtr( hWnd );
5674         if ( pFrame )
5675             pFrame->mbCandidateMode = FALSE;
5676         ImplSalYieldMutexRelease();
5677     }
5678 }
5679 
5680 // -----------------------------------------------------------------------
5681 #if WINVER >= 0x0500
5682 
5683 static LRESULT ImplHandleIMEReconvertString( HWND hWnd, LPARAM lParam )
5684 {
5685     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5686     LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam;
5687     LRESULT nRet = 0;
5688     SalSurroundingTextRequestEvent aEvt;
5689     aEvt.maText = UniString();
5690     aEvt.mnStart = aEvt.mnEnd = 0;
5691 
5692     UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_SETCOMPSTR );
5693     if( (nImeProps & SCS_CAP_SETRECONVERTSTRING) == 0 )
5694     {
5695 	// This IME does not support reconversion.
5696 	return 0;
5697     }
5698 
5699     if( !pReconvertString )
5700     {
5701 	// The first call for reconversion.
5702 	pFrame->CallCallback( SALEVENT_STARTRECONVERSION, (void*)NULL );
5703 
5704 	// Retrieve the surrounding text from the focused control.
5705 	pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5706 
5707 	if( aEvt.maText.Len() == 0 )
5708 	{
5709 	    return 0;
5710 	}
5711 
5712 	nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR);
5713     }
5714     else
5715     {
5716 	// The second call for reconversion.
5717 
5718 	// Retrieve the surrounding text from the focused control.
5719 	pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5720 	nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR);
5721 
5722 	pReconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
5723 	pReconvertString->dwStrLen = aEvt.maText.Len();
5724 	pReconvertString->dwCompStrOffset = aEvt.mnStart * sizeof(WCHAR);
5725 	pReconvertString->dwCompStrLen = aEvt.mnEnd - aEvt.mnStart;
5726 	pReconvertString->dwTargetStrOffset = pReconvertString->dwCompStrOffset;
5727 	pReconvertString->dwTargetStrLen = pReconvertString->dwCompStrLen;
5728 
5729 	memcpy( (LPWSTR)(pReconvertString + 1), aEvt.maText.GetBuffer(), (aEvt.maText.Len() + 1) * sizeof(WCHAR) );
5730     }
5731 
5732     // just return the required size of buffer to reconvert.
5733     return nRet;
5734 }
5735 
5736 // -----------------------------------------------------------------------
5737 
5738 static LRESULT ImplHandleIMEConfirmReconvertString( HWND hWnd, LPARAM lParam )
5739 {
5740     WinSalFrame* pFrame = GetWindowPtr( hWnd );
5741     LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam;
5742     SalSurroundingTextRequestEvent aEvt;
5743     aEvt.maText = UniString();
5744     aEvt.mnStart = aEvt.mnEnd = 0;
5745 
5746     pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt );
5747 
5748     sal_uLong nTmpStart = pReconvertString->dwCompStrOffset / sizeof(WCHAR);
5749     sal_uLong nTmpEnd = nTmpStart + pReconvertString->dwCompStrLen;
5750 
5751     if( nTmpStart != aEvt.mnStart || nTmpEnd != aEvt.mnEnd )
5752     {
5753 	SalSurroundingTextSelectionChangeEvent aSelEvt;
5754 	aSelEvt.mnStart = nTmpStart;
5755 	aSelEvt.mnEnd = nTmpEnd;
5756 
5757 	pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTSELECTIONCHANGE, (void*)&aSelEvt );
5758     }
5759 
5760     return TRUE;
5761 }
5762 
5763 #endif // WINVER >= 0x0500
5764 
5765 // -----------------------------------------------------------------------
5766 
5767 void SalTestMouseLeave()
5768 {
5769     SalData* pSalData = GetSalData();
5770 
5771     if ( pSalData->mhWantLeaveMsg && !::GetCapture() )
5772     {
5773         POINT aPt;
5774         GetCursorPos( &aPt );
5775         if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) )
5776             ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) );
5777     }
5778 }
5779 
5780 // -----------------------------------------------------------------------
5781 
5782 static int ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ,
5783                                  LRESULT& rResult )
5784 {
5785     POINT aPt;
5786     POINT aScreenPt;
5787     aScreenPt.x = (short)LOWORD( lParam );
5788     aScreenPt.y = (short)HIWORD( lParam );
5789     // Child-Fenster suchen, welches an der entsprechenden
5790     // Position liegt
5791     HWND hChildWnd;
5792     HWND hWheelWnd = hWnd;
5793     do
5794     {
5795         hChildWnd = hWheelWnd;
5796         aPt = aScreenPt;
5797         ScreenToClient( hChildWnd, &aPt );
5798         hWheelWnd = ChildWindowFromPointEx( hChildWnd, aPt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT );
5799     }
5800     while ( hWheelWnd && (hWheelWnd != hChildWnd) );
5801     if ( hWheelWnd && (hWheelWnd != hWnd) &&
5802          (hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) )
5803     {
5804         rResult = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
5805         return FALSE;
5806     }
5807 
5808     return TRUE;
5809 }
5810 
5811 // -----------------------------------------------------------------------
5812 
5813 LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
5814 {
5815     LRESULT     nRet = 0;
5816     static int  bInWheelMsg = FALSE;
5817 	static int	bInQueryEnd = FALSE;
5818 
5819     // By WM_CRETAE we connect the frame with the window handle
5820     if ( nMsg == WM_CREATE )
5821     {
5822         // Window-Instanz am Windowhandle speichern
5823         // Can also be used for the W-Version, because the struct
5824         // to access lpCreateParams is the same structure
5825         CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam;
5826         WinSalFrame* pFrame = (WinSalFrame*)pStruct->lpCreateParams;
5827 		if ( pFrame != 0 )
5828 		{
5829 			SetWindowPtr( hWnd, pFrame );
5830 			// HWND schon hier setzen, da schon auf den Instanzdaten
5831 			// gearbeitet werden kann, wenn Messages waehrend
5832 			// CreateWindow() gesendet werden
5833 			pFrame->mhWnd = hWnd;
5834 			pFrame->maSysData.hWnd = hWnd;
5835 		}
5836         return 0;
5837     }
5838 
5839     ImplSVData* pSVData = ImplGetSVData();
5840     // #i72707# TODO: the mbDeInit check will not be needed
5841     // once all windows that are not properly closed on exit got fixed
5842     if( pSVData->mbDeInit )
5843         return 0;
5844 
5845     if ( WM_USER_SYSTEM_WINDOW_ACTIVATED == nMsg )
5846     {
5847         if (pSVData->mpIntroWindow)
5848             pSVData->mpIntroWindow->Hide();
5849 
5850         return 0;
5851     }
5852 
5853 	bool bCheckTimers = false;
5854 
5855     switch( nMsg )
5856     {
5857         case WM_MOUSEMOVE:
5858         case WM_LBUTTONDOWN:
5859         case WM_MBUTTONDOWN:
5860         case WM_RBUTTONDOWN:
5861         case WM_LBUTTONUP:
5862         case WM_MBUTTONUP:
5863         case WM_RBUTTONUP:
5864         case WM_NCMOUSEMOVE:
5865         case SAL_MSG_MOUSELEAVE:
5866             ImplSalYieldMutexAcquireWithWait();
5867             rDef = !ImplHandleMouseMsg( hWnd, nMsg, wParam, lParam );
5868             ImplSalYieldMutexRelease();
5869             break;
5870 
5871         case WM_NCLBUTTONDOWN:
5872         case WM_NCMBUTTONDOWN:
5873         case WM_NCRBUTTONDOWN:
5874             ImplSalYieldMutexAcquireWithWait();
5875             ImplCallClosePopupsHdl( hWnd );   // close popups...
5876             ImplSalYieldMutexRelease();
5877             break;
5878 
5879         case WM_MOUSEACTIVATE:
5880             if ( LOWORD( lParam ) == HTCLIENT )
5881             {
5882                 ImplSalYieldMutexAcquireWithWait();
5883                 nRet = ImplHandleMouseActivateMsg( hWnd );
5884                 ImplSalYieldMutexRelease();
5885                 if ( nRet )
5886                 {
5887                     nRet = MA_NOACTIVATE;
5888                     rDef = FALSE;
5889                 }
5890             }
5891             break;
5892 
5893         case WM_KEYDOWN:
5894         case WM_KEYUP:
5895         case WM_DEADCHAR:
5896         case WM_CHAR:
5897         case WM_UNICHAR:    // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0
5898         case WM_SYSKEYDOWN:
5899         case WM_SYSKEYUP:
5900         case WM_SYSCHAR:
5901             ImplSalYieldMutexAcquireWithWait();
5902             rDef = !ImplHandleKeyMsg( hWnd, nMsg, wParam, lParam, nRet );
5903             ImplSalYieldMutexRelease();
5904             break;
5905 
5906         case WM_MOUSEWHEEL:
5907             // FALLTHROUGH intended
5908         case WM_MOUSEHWHEEL:
5909             // Gegen Rekursion absichern, falls wir vom IE oder dem externen
5910             // Fenster die Message wieder zurueckbekommen
5911             if ( !bInWheelMsg )
5912             {
5913                 bInWheelMsg++;
5914                 rDef = !ImplHandleWheelMsg( hWnd, nMsg, wParam, lParam );
5915                 // Wenn wir die Message nicht ausgewertet haben, schauen wir
5916                 // noch einmal nach, ob dort ein geplugtes Fenster steht,
5917                 // welches wir dann benachrichtigen
5918                 if ( rDef )
5919                     rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
5920                 bInWheelMsg--;
5921             }
5922             break;
5923 
5924         case WM_COMMAND:
5925             ImplSalYieldMutexAcquireWithWait();
5926             rDef = !ImplHandleCommand( hWnd, wParam, lParam );
5927             ImplSalYieldMutexRelease();
5928             break;
5929 
5930         case WM_INITMENUPOPUP:
5931             ImplSalYieldMutexAcquireWithWait();
5932             rDef = !ImplHandleMenuActivate( hWnd, wParam, lParam );
5933             ImplSalYieldMutexRelease();
5934             break;
5935 
5936         case WM_MENUSELECT:
5937             ImplSalYieldMutexAcquireWithWait();
5938             rDef = !ImplHandleMenuSelect( hWnd, wParam, lParam );
5939             ImplSalYieldMutexRelease();
5940             break;
5941 
5942         case WM_SYSCOMMAND:
5943             ImplSalYieldMutexAcquireWithWait();
5944             nRet = ImplHandleSysCommand( hWnd, wParam, lParam );
5945             ImplSalYieldMutexRelease();
5946             if ( nRet )
5947                 rDef = FALSE;
5948             break;
5949 
5950         case WM_MENUCHAR:
5951             nRet = ImplMenuChar( hWnd, wParam, lParam );
5952             if( nRet )
5953                 rDef = FALSE;
5954             break;
5955 
5956         case WM_MEASUREITEM:
5957             nRet = ImplMeasureItem(hWnd, wParam, lParam);
5958             if( nRet )
5959                 rDef = FALSE;
5960             break;
5961 
5962         case WM_DRAWITEM:
5963             nRet = ImplDrawItem(hWnd, wParam, lParam);
5964             if( nRet )
5965                 rDef = FALSE;
5966             break;
5967 
5968         case WM_MOVE:
5969         case SAL_MSG_POSTMOVE:
5970             ImplHandleMoveMsg( hWnd );
5971             rDef = FALSE;
5972             break;
5973         case WM_SIZE:
5974             ImplHandleSizeMsg( hWnd, wParam, lParam );
5975             rDef = FALSE;
5976             break;
5977         case SAL_MSG_POSTCALLSIZE:
5978             ImplCallSizeHdl( hWnd );
5979             rDef = FALSE;
5980             break;
5981 
5982         case WM_GETMINMAXINFO:
5983             if ( ImplHandleMinMax( hWnd, lParam ) )
5984                 rDef = FALSE;
5985             break;
5986 
5987         case WM_ERASEBKGND:
5988             nRet = 1;
5989             rDef = FALSE;
5990             break;
5991         case WM_PAINT:
5992             bCheckTimers = ImplHandlePaintMsg( hWnd );
5993             rDef = FALSE;
5994             break;
5995         case SAL_MSG_POSTPAINT:
5996             ImplHandlePaintMsg2( hWnd, (RECT*)wParam );
5997 			bCheckTimers = true;
5998             rDef = FALSE;
5999             break;
6000 
6001         case SAL_MSG_FORCEPALETTE:
6002             ImplHandleForcePalette( hWnd );
6003             rDef = FALSE;
6004             break;
6005 
6006         case WM_QUERYNEWPALETTE:
6007         case SAL_MSG_POSTQUERYNEWPAL:
6008             nRet = ImplHandlePalette( TRUE, hWnd, nMsg, wParam, lParam, rDef );
6009             break;
6010 
6011         case WM_ACTIVATE:
6012             // Wenn wir aktiviert werden, dann wollen wir auch unsere
6013             // Palette setzen. Wir machen dieses in Activate,
6014             // damit andere externe Child-Fenster auch unsere Palette
6015             // ueberschreiben koennen. So wird unsere jedenfalls nur einmal
6016             // gesetzt und nicht immer rekursiv, da an allen anderen Stellen
6017             // diese nur als Background-Palette gesetzt wird
6018             if ( LOWORD( wParam ) != WA_INACTIVE )
6019                 ImplSendMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 );
6020             break;
6021 
6022         case WM_ENABLE:
6023             // #95133# a system dialog is opened/closed, using our app window as parent
6024             {
6025                 WinSalFrame* pFrame = GetWindowPtr( hWnd );
6026                 Window *pWin = NULL;
6027 	            if( pFrame )
6028 	                pWin = pFrame->GetWindow();
6029 
6030                 if( !wParam )
6031                 {
6032                     ImplSVData* pSVData = ImplGetSVData();
6033                     pSVData->maAppData.mnModalMode++;
6034 
6035                     // #106431#, hide SplashScreen
6036                     if( pSVData->mpIntroWindow )
6037                         pSVData->mpIntroWindow->Hide();
6038 
6039                     if( pWin )
6040                     {
6041                         pWin->EnableInput( FALSE, TRUE, TRUE, NULL );
6042                         pWin->ImplIncModalCount();  // #106303# support frame based modal count
6043                     }
6044                 }
6045                 else
6046                 {
6047                     ImplGetSVData()->maAppData.mnModalMode--;
6048                     if( pWin )
6049                     {
6050                         pWin->EnableInput( TRUE, TRUE, TRUE, NULL );
6051                         pWin->ImplDecModalCount();  // #106303# support frame based modal count
6052                     }
6053                 }
6054             }
6055             break;
6056 
6057         case WM_KILLFOCUS:
6058             DestroyCaret();
6059         case WM_SETFOCUS:
6060         case SAL_MSG_POSTFOCUS:
6061             ImplHandleFocusMsg( hWnd );
6062             rDef = FALSE;
6063             break;
6064 
6065         case WM_CLOSE:
6066             ImplHandleCloseMsg( hWnd );
6067             rDef = FALSE;
6068             break;
6069 
6070         case WM_QUERYENDSESSION:
6071 			if( !bInQueryEnd )
6072 			{
6073 				// handle queryendsession only once
6074 				bInQueryEnd = TRUE;
6075 				nRet = !ImplHandleShutDownMsg( hWnd );
6076 				rDef = FALSE;
6077 
6078 				// Issue #16314#: ImplHandleShutDownMsg causes a PostMessage in case of allowing shutdown.
6079 				// This posted message was never processed and cause Windows XP to hang after log off
6080 				// if there are multiple sessions and the current session wasn't the first one started.
6081 				// So if shutdown is allowed we assume that a post message was done and retrieve all
6082 				// messages in the message queue and dispatch them before we return control to the system.
6083 
6084 				if ( nRet )
6085 				{
6086 					MSG	msg;
6087 
6088 					while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
6089 					{
6090 						DispatchMessage( &msg );
6091 					}
6092 				}
6093 			}
6094 			else
6095 			{
6096 				ImplSalYieldMutexAcquireWithWait();
6097 				ImplSalYieldMutexRelease();
6098 				rDef = TRUE;
6099 			}
6100             break;
6101 
6102 		case WM_ENDSESSION:
6103 			if( !wParam )
6104 				bInQueryEnd = FALSE; // no shutdown: allow query again
6105 			nRet = FALSE;
6106 			rDef = FALSE;
6107 			break;
6108 
6109         case WM_DISPLAYCHANGE:
6110         case WM_SETTINGCHANGE:
6111         case WM_DEVMODECHANGE:
6112         case WM_FONTCHANGE:
6113         case WM_SYSCOLORCHANGE:
6114         case WM_TIMECHANGE:
6115             ImplHandleSettingsChangeMsg( hWnd, nMsg, wParam, lParam );
6116             break;
6117 
6118         case WM_THEMECHANGED:
6119             GetSalData()->mbThemeChanged = TRUE;
6120             break;
6121 
6122         case SAL_MSG_USEREVENT:
6123             ImplHandleUserEvent( hWnd, lParam );
6124             rDef = FALSE;
6125             break;
6126 
6127         case SAL_MSG_CAPTUREMOUSE:
6128             SetCapture( hWnd );
6129             rDef = FALSE;
6130             break;
6131         case SAL_MSG_RELEASEMOUSE:
6132             if ( ::GetCapture() == hWnd )
6133                 ReleaseCapture();
6134             rDef = FALSE;
6135             break;
6136         case SAL_MSG_TOTOP:
6137             ImplSalToTop( hWnd, (sal_uInt16)wParam );
6138             rDef = FALSE;
6139             break;
6140         case SAL_MSG_SHOW:
6141             ImplSalShow( hWnd, (sal_Bool)wParam, (sal_Bool)lParam );
6142             rDef = FALSE;
6143             break;
6144         case SAL_MSG_SETINPUTCONTEXT:
6145             ImplSalFrameSetInputContext( hWnd, (const SalInputContext*)(void*)lParam );
6146             rDef = FALSE;
6147             break;
6148         case SAL_MSG_ENDEXTTEXTINPUT:
6149             ImplSalFrameEndExtTextInput( hWnd, (sal_uInt16)(sal_uLong)(void*)wParam );
6150             rDef = FALSE;
6151             break;
6152 
6153         case WM_INPUTLANGCHANGE:
6154             ImplHandleInputLangChange( hWnd, wParam, lParam );
6155             break;
6156 
6157         case WM_IME_CHAR:
6158             // #103487#, some IMEs (eg, those that do not work onspot)
6159             //           may send WM_IME_CHAR instead of WM_IME_COMPOSITION
6160             // we just handle it like a WM_CHAR message - seems to work fine
6161             ImplSalYieldMutexAcquireWithWait();
6162             rDef = !ImplHandleKeyMsg( hWnd, WM_CHAR, wParam, lParam, nRet );
6163             ImplSalYieldMutexRelease();
6164             break;
6165 
6166          case WM_IME_STARTCOMPOSITION:
6167             rDef = ImplHandleIMEStartComposition( hWnd );
6168             break;
6169 
6170         case WM_IME_COMPOSITION:
6171             rDef = ImplHandleIMEComposition( hWnd, lParam );
6172             break;
6173 
6174         case WM_IME_ENDCOMPOSITION:
6175             rDef = ImplHandleIMEEndComposition( hWnd );
6176             break;
6177 
6178         case WM_IME_NOTIFY:
6179             ImplHandleIMENotify( hWnd, wParam );
6180             break;
6181         case WM_APPCOMMAND:
6182             if( ImplHandleAppCommand( hWnd, lParam ) )
6183             {
6184                 rDef = false;
6185                 nRet = 1;
6186             }
6187             break;
6188 #if WINVER >= 0x0500
6189         case WM_IME_REQUEST:
6190             if ( PtrToInt( wParam ) == IMR_RECONVERTSTRING )
6191             {
6192                 nRet = ImplHandleIMEReconvertString( hWnd, lParam );
6193                 rDef = FALSE;
6194             }
6195 	    else if( PtrToInt( wParam ) == IMR_CONFIRMRECONVERTSTRING )
6196 	    {
6197 		nRet = ImplHandleIMEConfirmReconvertString( hWnd, lParam );
6198 		rDef = FALSE;
6199 	    }
6200             break;
6201 #endif // WINVER >= 0x0500
6202     }
6203 
6204     // WheelMouse-Message abfangen
6205     if ( rDef && (nMsg == aSalShlData.mnWheelMsgId) && aSalShlData.mnWheelMsgId )
6206     {
6207         // Gegen Rekursion absichern, falls wir vom IE oder dem externen
6208         // Fenster die Message wieder zurueckbekommen
6209         if ( !bInWheelMsg )
6210         {
6211             bInWheelMsg++;
6212             // Zuerst wollen wir die Message dispatchen und dann darf auch
6213             // das SystemWindow drankommen
6214             WORD nKeyState = 0;
6215             if ( GetKeyState( VK_SHIFT ) & 0x8000 )
6216                 nKeyState |= MK_SHIFT;
6217             if ( GetKeyState( VK_CONTROL ) & 0x8000 )
6218                 nKeyState |= MK_CONTROL;
6219             // Mutex handling is inside from this call
6220             rDef = !ImplHandleWheelMsg( hWnd,
6221                                         WM_MOUSEWHEEL,
6222                                         MAKEWPARAM( nKeyState, (WORD)wParam ),
6223                                         lParam );
6224             if ( rDef )
6225             {
6226                 HWND hWheelWnd = ::GetFocus();
6227                 if ( hWheelWnd && (hWheelWnd != hWnd) )
6228                 {
6229                     nRet = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam );
6230                     rDef = FALSE;
6231                 }
6232                 else
6233                     rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet );
6234             }
6235             bInWheelMsg--;
6236         }
6237     }
6238 
6239 	if( bCheckTimers )
6240 	{
6241 		SalData* pSalData = GetSalData();
6242 		if( pSalData->mnNextTimerTime )
6243 		{
6244 			DWORD nCurTime = GetTickCount();
6245 			if( pSalData->mnNextTimerTime < nCurTime )
6246 			{
6247 				MSG aMsg;
6248 				if( ! ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE | PM_NOYIELD ) )
6249 					ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_POSTTIMER, 0, nCurTime );
6250 			}
6251 		}
6252 	}
6253 
6254     return nRet;
6255 }
6256 
6257 LRESULT CALLBACK SalFrameWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
6258 {
6259     int bDef = TRUE;
6260     LRESULT nRet = 0;
6261 #ifdef __MINGW32__
6262     jmp_buf jmpbuf;
6263     __SEHandler han;
6264     if (__builtin_setjmp(jmpbuf) == 0)
6265     {
6266         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
6267 #else
6268     __try
6269     {
6270 #endif
6271         nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
6272     }
6273 #ifdef __MINGW32__
6274     han.Reset();
6275 #else
6276     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
6277     {
6278     }
6279 #endif
6280     if ( bDef )
6281         nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
6282     return nRet;
6283 }
6284 
6285 LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
6286 {
6287     int bDef = TRUE;
6288     LRESULT nRet = 0;
6289 #ifdef __MINGW32__
6290     jmp_buf jmpbuf;
6291     __SEHandler han;
6292     if (__builtin_setjmp(jmpbuf) == 0)
6293     {
6294         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
6295 #else
6296     __try
6297     {
6298 #endif
6299         nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef );
6300     }
6301 #ifdef __MINGW32__
6302     han.Reset();
6303 #else
6304     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
6305     {
6306     }
6307 #endif
6308 
6309     if ( bDef )
6310         nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
6311     return nRet;
6312 }
6313 
6314 // -----------------------------------------------------------------------
6315 
6316 sal_Bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult )
6317 {
6318 	// handle all messages concerning all frames so they get processed only once
6319     // Must work for Unicode and none Unicode
6320 	sal_Bool bResult = FALSE;
6321     if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) )
6322     {
6323         int bDef = TRUE;
6324         rlResult = ImplHandlePalette( FALSE, hWnd, nMsg, wParam, lParam, bDef );
6325         bResult = (bDef != 0);
6326     }
6327 	else if( nMsg == WM_DISPLAYCHANGE )
6328 	{
6329 		WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
6330 		if( pSys )
6331 			pSys->clearMonitors();
6332 		bResult = (pSys != NULL);
6333 	}
6334 	return bResult;
6335 }
6336 
6337 // -----------------------------------------------------------------------
6338 
6339 sal_Bool ImplWriteLastError( DWORD lastError, const char *szApiCall )
6340 {
6341     static int first=1;
6342     // if VCL_LOGFILE_ENABLED is set, Win32 API error messages can be written
6343     // to %TMP%/vcl.log or %TEMP%/vcl.log
6344     static char *logEnabled = getenv("VCL_LOGFILE_ENABLED");
6345     if( logEnabled )
6346     {
6347         sal_Bool bSuccess = FALSE;
6348         static char *szTmp = getenv("TMP");
6349         if( !szTmp || !*szTmp )
6350             szTmp = getenv("TEMP");
6351         if( szTmp && *szTmp )
6352         {
6353             char fname[5000];
6354             strcpy( fname, szTmp );
6355             if( fname[strlen(fname) - 1] != '\\' )
6356                 strcat( fname, "\\");
6357             strcat( fname, "vcl.log" );
6358             FILE *fp = fopen( fname, "a" ); // always append
6359             if( fp )
6360             {
6361                 if( first )
6362                 {
6363                     first = 0;
6364                     fprintf( fp, "Process ID: %d (0x%x)\n", GetCurrentProcessId(), GetCurrentProcessId() );
6365                 }
6366                 time_t aclock;
6367                 time( &aclock );                           // Get time in seconds
6368                 struct tm *newtime = localtime( &aclock ); // Convert time to struct tm form
6369                 fprintf( fp, asctime( newtime ) );         // print time stamp
6370 
6371                 fprintf( fp, "%s returned %u (0x%x)\n", szApiCall, lastError, lastError );
6372                 bSuccess = TRUE;    // may be FormatMessage fails but we wrote at least the error code
6373 
6374                 LPVOID lpMsgBuf;
6375                 if (FormatMessageA(
6376                     FORMAT_MESSAGE_ALLOCATE_BUFFER |
6377                     FORMAT_MESSAGE_FROM_SYSTEM |
6378                     FORMAT_MESSAGE_IGNORE_INSERTS,
6379                     NULL,
6380                     lastError,
6381                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
6382                     (LPSTR) &lpMsgBuf,
6383                     0,
6384                     NULL ))
6385                 {
6386                     fprintf( fp, " %s\n", (LPSTR)lpMsgBuf );
6387                     LocalFree( lpMsgBuf );
6388                 }
6389 
6390                 fclose( fp );
6391             }
6392         }
6393         return bSuccess;
6394     }
6395     else
6396         return TRUE;
6397 }
6398 
6399 // -----------------------------------------------------------------------
6400 
6401