xref: /aoo41x/main/vcl/win/source/window/salobj.cxx (revision 9f62ea84)
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 #include <string.h>
28 
29 #include <tools/debug.hxx>
30 #include <tools/svwin.h>
31 
32 #include <vcl/svapp.hxx>
33 
34 #include <win/wincomp.hxx>
35 #include <win/saldata.hxx>
36 #include <win/salinst.h>
37 #include <win/salframe.h>
38 #include <win/salobj.h>
39 
40 // =======================================================================
41 
42 static sal_Bool ImplIsSysWindowOrChild( HWND hWndParent, HWND hWndChild )
43 {
44 	if ( hWndParent == hWndChild )
45 		return TRUE;
46 
47 	HWND hTempWnd = ::GetParent( hWndChild );
48 	while ( hTempWnd )
49 	{
50 		// Ab nicht Child-Fenstern hoeren wir auf zu suchen
51 		if ( !(GetWindowStyle( hTempWnd ) & WS_CHILD) )
52 			return FALSE;
53 		if ( hTempWnd == hWndParent )
54 			return TRUE;
55 		hTempWnd = ::GetParent( hTempWnd );
56 	}
57 
58 	return FALSE;
59 }
60 
61 // -----------------------------------------------------------------------
62 
63 WinSalObject* ImplFindSalObject( HWND hWndChild )
64 {
65 	SalData*        pSalData = GetSalData();
66 	WinSalObject*	pObject = pSalData->mpFirstObject;
67 	while ( pObject )
68 	{
69 		if ( ImplIsSysWindowOrChild( pObject->mhWndChild, hWndChild ) )
70 			return pObject;
71 
72 		pObject = pObject->mpNextObject;
73 	}
74 
75 	return NULL;
76 }
77 
78 // -----------------------------------------------------------------------
79 
80 WinSalFrame* ImplFindSalObjectFrame( HWND hWnd )
81 {
82 	WinSalFrame* pFrame = NULL;
83 	WinSalObject* pObject = ImplFindSalObject( hWnd );
84 	if ( pObject )
85 	{
86 		// Dazugehoerenden Frame suchen
87 		HWND hWnd = ::GetParent( pObject->mhWnd );
88 		pFrame = GetSalData()->mpFirstFrame;
89 		while ( pFrame )
90 		{
91 			if ( pFrame->mhWnd == hWnd )
92 				break;
93 
94 			pFrame = pFrame->mpNextFrame;
95 		}
96 	}
97 
98 	return pFrame;
99 }
100 
101 // -----------------------------------------------------------------------
102 
103 sal_Bool ImplInterceptChildWindowKeyDown( MSG& rMsg )
104 {
105     sal_Bool bResult = sal_False;
106     if ( rMsg.message == WM_KEYDOWN )
107     {
108         wchar_t pClassName[10];
109         sal_Int32 nLen = GetClassNameW( rMsg.hwnd, pClassName, 10 );
110         if ( !( nLen == 9 && wcsncmp( pClassName, SAL_OBJECT_CLASSNAMEW, nLen ) == 0 ) )
111         {
112             // look for the first SalObject in the parent hierarchy
113             HWND hWin = rMsg.hwnd;
114             HWND hLastOLEWindow = hWin;
115             WinSalObject* pSalObj = NULL;
116             do
117             {
118                 hLastOLEWindow = hWin;
119                 hWin = ::GetParent( hWin );
120                 if ( hWin )
121                 {
122                     nLen = GetClassNameW( hWin, pClassName, 10 );
123                     if ( nLen == 9 && wcsncmp( pClassName, SAL_OBJECT_CLASSNAMEW, nLen ) == 0 )
124                         pSalObj = GetSalObjWindowPtr( hWin );
125                 }
126             } while( hWin && !pSalObj );
127 
128             if ( pSalObj && pSalObj->mbInterceptChildWindowKeyDown && pSalObj->maSysData.hWnd )
129             {
130                 bResult = ( 1 == ImplSendMessage( pSalObj->maSysData.hWnd, rMsg.message, rMsg.wParam, rMsg.lParam ) );
131             }
132         }
133     }
134 
135     return bResult;
136 }
137 
138 // -----------------------------------------------------------------------
139 
140 
141 // -----------------------------------------------------------------------
142 
143 LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
144 {
145 	// Used for Unicode and none Unicode
146 	SalData* pSalData = GetSalData();
147 
148 	if ( (nCode >= 0) && lParam )
149 	{
150 		CWPSTRUCT* pData = (CWPSTRUCT*)lParam;
151 		if ( (pData->message != WM_KEYDOWN) &&
152 			 (pData->message != WM_KEYUP) )
153 			pSalData->mnSalObjWantKeyEvt = 0;
154 
155 		// Testen, ob wir Daten fuer ein SalObject-Fenster behandeln
156 		// muessen
157 		WinSalObject* pObject;
158 		if ( pData->message == WM_SETFOCUS )
159 		{
160 			pObject = ImplFindSalObject( pData->hwnd );
161 			if ( pObject )
162 			{
163 				pObject->mhLastFocusWnd = pData->hwnd;
164 				if ( ImplSalYieldMutexTryToAcquire() )
165 				{
166 					pObject->CallCallback( SALOBJ_EVENT_GETFOCUS, 0 );
167 					ImplSalYieldMutexRelease();
168 				}
169 				else
170 					ImplPostMessage( pObject->mhWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 );
171 			}
172 		}
173 		else if ( pData->message == WM_KILLFOCUS )
174 		{
175 			pObject = ImplFindSalObject( pData->hwnd );
176 			if ( pObject && !ImplFindSalObject( (HWND)pData->wParam ) )
177 			{
178 				// LoseFocus nur rufen, wenn wirklich kein ChildFenster
179 				// den Focus bekommt
180 				if ( !pData->wParam || !ImplFindSalObject( (HWND)pData->wParam ) )
181 				{
182 					if ( ImplSalYieldMutexTryToAcquire() )
183 					{
184 						pObject->CallCallback( SALOBJ_EVENT_LOSEFOCUS, 0 );
185 						ImplSalYieldMutexRelease();
186 					}
187 					else
188 						ImplPostMessage( pObject->mhWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 );
189 				}
190 				else
191 					pObject->mhLastFocusWnd = (HWND)pData->wParam;
192 			}
193 		}
194 	}
195 
196 	return CallNextHookEx( pSalData->mhSalObjMsgHook, nCode, wParam, lParam );
197 }
198 
199 // -----------------------------------------------------------------------
200 
201 sal_Bool ImplSalPreDispatchMsg( MSG* pMsg )
202 {
203 	// Used for Unicode and none Unicode
204 	SalData*	    pSalData = GetSalData();
205 	WinSalObject*	pObject;
206 
207 	if ( (pMsg->message == WM_LBUTTONDOWN) ||
208 		 (pMsg->message == WM_RBUTTONDOWN) ||
209 		 (pMsg->message == WM_MBUTTONDOWN) )
210 	{
211 		ImplSalYieldMutexAcquireWithWait();
212 		pObject = ImplFindSalObject( pMsg->hwnd );
213 		if ( pObject && !pObject->IsMouseTransparent() )
214 		    ImplPostMessage( pObject->mhWnd, SALOBJ_MSG_TOTOP, 0, 0 );
215 		ImplSalYieldMutexRelease();
216 	}
217 
218 	if ( (pMsg->message == WM_KEYDOWN) ||
219 		 (pMsg->message == WM_KEYUP) )
220 	{
221 		// KeyEvents wollen wir nach Moeglichkeit auch abarbeiten,
222 		// wenn das Control diese nicht selber auswertet
223 		// SysKeys werden als WM_SYSCOMMAND verarbeitet
224 		// Char-Events verarbeiten wir nicht, da wir nur
225 		// Accelerator relevante Keys verarbeiten wollen
226 		sal_Bool bWantedKeyCode = FALSE;
227 		// A-Z, 0-9 nur in Verbindung mit Control-Taste
228 		if ( ((pMsg->wParam >= 65) && (pMsg->wParam <= 90)) ||
229 			 ((pMsg->wParam >= 48) && (pMsg->wParam <= 57)) )
230 		{
231 			if ( GetKeyState( VK_CONTROL ) & 0x8000 )
232 				bWantedKeyCode = TRUE;
233 		}
234 		else if ( ((pMsg->wParam >= VK_F1) && (pMsg->wParam <= VK_F24)) ||
235 				  ((pMsg->wParam >= VK_SPACE) && (pMsg->wParam <= VK_HELP)) ||
236 				  (pMsg->wParam == VK_BACK) || (pMsg->wParam == VK_TAB) ||
237 				  (pMsg->wParam == VK_CLEAR) || (pMsg->wParam == VK_RETURN) ||
238 				  (pMsg->wParam == VK_ESCAPE) )
239 			bWantedKeyCode = TRUE;
240 		if ( bWantedKeyCode )
241 		{
242 			ImplSalYieldMutexAcquireWithWait();
243 			pObject = ImplFindSalObject( pMsg->hwnd );
244 			if ( pObject )
245 				pSalData->mnSalObjWantKeyEvt = pMsg->wParam;
246 			ImplSalYieldMutexRelease();
247 		}
248 	}
249 	// Hier WM_SYSCHAR abfangen, um mit Alt+Taste evtl. Menu zu aktivieren
250 	else if ( pMsg->message == WM_SYSCHAR )
251 	{
252 		pSalData->mnSalObjWantKeyEvt = 0;
253 
254 		sal_uInt16 nKeyCode = LOWORD( pMsg->wParam );
255 		// Nur 0-9 und A-Z
256 		if ( ((nKeyCode >= 48) && (nKeyCode <= 57)) ||
257 			 ((nKeyCode >= 65) && (nKeyCode <= 90)) ||
258 			 ((nKeyCode >= 97) && (nKeyCode <= 122)) )
259 		{
260 			sal_Bool bRet = FALSE;
261 			ImplSalYieldMutexAcquireWithWait();
262 			pObject = ImplFindSalObject( pMsg->hwnd );
263 			if ( pObject )
264 			{
265 				if ( pMsg->hwnd == ::GetFocus() )
266 				{
267 					WinSalFrame* pFrame = ImplFindSalObjectFrame( pMsg->hwnd );
268 					if ( pFrame )
269 					{
270 						if ( ImplHandleSalObjSysCharMsg( pFrame->mhWnd, pMsg->wParam, pMsg->lParam ) )
271 							bRet = TRUE;
272 					}
273 				}
274 			}
275 			ImplSalYieldMutexRelease();
276 			if ( bRet )
277 				return TRUE;
278 		}
279 	}
280 	else
281 		pSalData->mnSalObjWantKeyEvt = 0;
282 
283 	return FALSE;
284 }
285 
286 // -----------------------------------------------------------------------
287 
288 void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT /* nDispatchResult */ )
289 {
290 	// Used for Unicode and none Unicode
291 	SalData*	    pSalData = GetSalData();
292 	WinSalFrame*	pFrame;
293 
294 	if ( (pMsg->message == WM_KEYDOWN) || (pMsg->message == WM_KEYUP) )
295 	{
296 		if ( pSalData->mnSalObjWantKeyEvt == pMsg->wParam )
297 		{
298 			pSalData->mnSalObjWantKeyEvt = 0;
299 			if ( pMsg->hwnd == ::GetFocus() )
300 			{
301 				ImplSalYieldMutexAcquireWithWait();
302 				pFrame = ImplFindSalObjectFrame( pMsg->hwnd );
303 				if ( pFrame )
304 					ImplHandleSalObjKeyMsg( pFrame->mhWnd, pMsg->message, pMsg->wParam, pMsg->lParam );
305 				ImplSalYieldMutexRelease();
306 			}
307 		}
308 	}
309 
310 	pSalData->mnSalObjWantKeyEvt = 0;
311 }
312 
313 // =======================================================================
314 
315 LRESULT CALLBACK SalSysObjWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
316 {
317 	WinSalObject*	pSysObj;
318 	LRESULT      	nRet = 0;
319 
320 	switch( nMsg )
321 	{
322 		case WM_ERASEBKGND:
323 			nRet = 1;
324 			rDef = FALSE;
325 			break;
326 		case WM_PAINT:
327 			{
328 			PAINTSTRUCT aPs;
329 			BeginPaint( hWnd, &aPs );
330 			EndPaint( hWnd, &aPs );
331 			rDef = FALSE;
332 			}
333 			break;
334 
335 		case WM_PARENTNOTIFY:
336 			{
337 			UINT nNotifyMsg = LOWORD( wParam );
338 			if ( (nNotifyMsg == WM_LBUTTONDOWN) ||
339 				 (nNotifyMsg == WM_RBUTTONDOWN) ||
340 				 (nNotifyMsg == WM_MBUTTONDOWN) )
341 			{
342 				ImplSalYieldMutexAcquireWithWait();
343 				pSysObj = GetSalObjWindowPtr( hWnd );
344 				if ( pSysObj && !pSysObj->IsMouseTransparent() )
345 				    pSysObj->CallCallback( SALOBJ_EVENT_TOTOP, 0 );
346 				ImplSalYieldMutexRelease();
347 			}
348 			}
349 			break;
350 
351 		case WM_MOUSEACTIVATE:
352             {
353 			ImplSalYieldMutexAcquireWithWait();
354 			pSysObj = GetSalObjWindowPtr( hWnd );
355 			if ( pSysObj && !pSysObj->IsMouseTransparent() )
356 			    ImplPostMessage( hWnd, SALOBJ_MSG_TOTOP, 0, 0 );
357 		    ImplSalYieldMutexRelease();
358             }
359 			break;
360 
361 		case SALOBJ_MSG_TOTOP:
362 			if ( ImplSalYieldMutexTryToAcquire() )
363 			{
364 				pSysObj = GetSalObjWindowPtr( hWnd );
365 				pSysObj->CallCallback( SALOBJ_EVENT_TOTOP, 0 );
366 				ImplSalYieldMutexRelease();
367 				rDef = FALSE;
368 			}
369 			else
370 				ImplPostMessage( hWnd, SALOBJ_MSG_TOTOP, 0, 0 );
371 			break;
372 
373 		case SALOBJ_MSG_POSTFOCUS:
374 			if ( ImplSalYieldMutexTryToAcquire() )
375 			{
376 				pSysObj = GetSalObjWindowPtr( hWnd );
377 				HWND	hFocusWnd = ::GetFocus();
378 				sal_uInt16 nEvent;
379 				if ( hFocusWnd && ImplIsSysWindowOrChild( hWnd, hFocusWnd ) )
380 					nEvent = SALOBJ_EVENT_GETFOCUS;
381 				else
382 					nEvent = SALOBJ_EVENT_LOSEFOCUS;
383 				pSysObj->CallCallback( nEvent, 0 );
384 				ImplSalYieldMutexRelease();
385 			}
386 			else
387 				ImplPostMessage( hWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 );
388 			rDef = FALSE;
389 			break;
390 
391 		case WM_SIZE:
392 			{
393 			HWND hWndChild = GetWindow( hWnd, GW_CHILD );
394 			if ( hWndChild )
395 			{
396 				SetWindowPos( hWndChild,
397 							  0, 0,  0, (int)LOWORD( lParam ), (int)HIWORD( lParam ),
398 							  SWP_NOZORDER | SWP_NOACTIVATE );
399 			}
400 			}
401 			rDef = FALSE;
402 			break;
403 
404 		case WM_CREATE:
405 			{
406 			// Window-Instanz am Windowhandle speichern
407 			// Can also be used for the W-Version, because the struct
408 			// to access lpCreateParams is the same structure
409 			CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam;
410 			pSysObj = (WinSalObject*)pStruct->lpCreateParams;
411 			SetSalObjWindowPtr( hWnd, pSysObj );
412 			// HWND schon hier setzen, da schon auf den Instanzdaten
413 			// gearbeitet werden kann, wenn Messages waehrend
414 			// CreateWindow() gesendet werden
415 			pSysObj->mhWnd = hWnd;
416 			rDef = FALSE;
417 			}
418 			break;
419 	}
420 
421 	return nRet;
422 }
423 
424 LRESULT CALLBACK SalSysObjWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
425 {
426 	int bDef = TRUE;
427 	LRESULT nRet = SalSysObjWndProc( hWnd, nMsg, wParam, lParam, bDef );
428 	if ( bDef )
429 		nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
430 	return nRet;
431 }
432 
433 LRESULT CALLBACK SalSysObjWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
434 {
435 	int bDef = TRUE;
436 	LRESULT nRet = SalSysObjWndProc( hWnd, nMsg, wParam, lParam, bDef );
437 	if ( bDef )
438 		nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
439 	return nRet;
440 }
441 
442 // -----------------------------------------------------------------------
443 
444 LRESULT CALLBACK SalSysObjChildWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
445 {
446 	LRESULT nRet = 0;
447 
448 	switch( nMsg )
449 	{
450 		// Wegen PlugIn's loeschen wir erstmal den Hintergrund
451 		case WM_ERASEBKGND:
452             {
453 	            WinSalObject* pSysObj = GetSalObjWindowPtr( ::GetParent( hWnd ) );
454 
455                 if( pSysObj && !pSysObj->IsEraseBackgroundEnabled() )
456                 {
457                     // do not erase background
458 			        nRet = 1;
459 			        rDef = FALSE;
460                 }
461             }
462 			break;
463 
464 		case WM_PAINT:
465 			{
466 			PAINTSTRUCT aPs;
467 			BeginPaint( hWnd, &aPs );
468 			EndPaint( hWnd, &aPs );
469 			rDef = FALSE;
470 			}
471 			break;
472 
473         case WM_MOUSEMOVE:
474         case WM_LBUTTONDOWN:
475         case WM_MBUTTONDOWN:
476         case WM_RBUTTONDOWN:
477         case WM_LBUTTONUP:
478         case WM_MBUTTONUP:
479         case WM_RBUTTONUP:
480             {
481 	            WinSalObject* pSysObj;
482                 pSysObj = GetSalObjWindowPtr( ::GetParent( hWnd ) );
483 
484                 if( pSysObj && pSysObj->IsMouseTransparent() )
485                 {
486                     // forward mouse events to parent frame
487                     HWND hWndParent = ::GetParent( pSysObj->mhWnd );
488 
489                     // transform coordinates
490                     POINT pt;
491                     pt.x = (long) LOWORD( lParam );
492                     pt.y = (long) HIWORD( lParam );
493                     MapWindowPoints( hWnd, hWndParent, &pt, 1 );
494                     lParam = MAKELPARAM( (WORD) pt.x, (WORD) pt.y );
495 
496 		            nRet = ImplSendMessage( hWndParent, nMsg, wParam, lParam );
497                     rDef = FALSE;
498                 }
499             }
500             break;
501 	}
502 
503 	return nRet;
504 }
505 
506 LRESULT CALLBACK SalSysObjChildWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
507 {
508 	int bDef = TRUE;
509 	LRESULT nRet = SalSysObjChildWndProc( hWnd, nMsg, wParam, lParam, bDef );
510 	if ( bDef )
511 		nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
512 	return nRet;
513 }
514 
515 LRESULT CALLBACK SalSysObjChildWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
516 {
517 	int bDef = TRUE;
518 	LRESULT nRet = SalSysObjChildWndProc( hWnd, nMsg, wParam, lParam, bDef );
519 	if ( bDef )
520 		nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
521 	return nRet;
522 }
523 
524 // =======================================================================
525 
526 SalObject* ImplSalCreateObject( WinSalInstance* pInst, WinSalFrame* pParent )
527 {
528 	SalData* pSalData = GetSalData();
529 
530 	// Hook installieren, wenn es das erste SalObject ist
531 	if ( !pSalData->mpFirstObject )
532 	{
533 		pSalData->mhSalObjMsgHook = SetWindowsHookExW( WH_CALLWNDPROC,
534 														   SalSysMsgProc,
535 														   pSalData->mhInst,
536 														   pSalData->mnAppThreadId );
537 	}
538 
539 	if ( !pSalData->mbObjClassInit )
540 	{
541         // #95301# shockwave plugin has bug; expects ASCII functions to be used
542 		if ( false )//aSalShlData.mbWNT )
543 		{
544 			WNDCLASSEXW aWndClassEx;
545 			aWndClassEx.cbSize			= sizeof( aWndClassEx );
546 			aWndClassEx.style			= 0;
547 			aWndClassEx.lpfnWndProc 	= SalSysObjWndProcW;
548 			aWndClassEx.cbClsExtra		= 0;
549 			aWndClassEx.cbWndExtra		= SAL_OBJECT_WNDEXTRA;
550 			aWndClassEx.hInstance		= pSalData->mhInst;
551 			aWndClassEx.hIcon			= 0;
552 			aWndClassEx.hIconSm 		= 0;
553 			aWndClassEx.hCursor 		= LoadCursor( 0, IDC_ARROW );
554 			aWndClassEx.hbrBackground	= 0;
555 			aWndClassEx.lpszMenuName	= 0;
556 			aWndClassEx.lpszClassName	= SAL_OBJECT_CLASSNAMEW;
557 			if ( RegisterClassExW( &aWndClassEx ) )
558 			{
559 				// Wegen PlugIn's loeschen wir erstmal den Hintergrund
560 				aWndClassEx.cbWndExtra		= 0;
561 				aWndClassEx.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
562 				aWndClassEx.lpfnWndProc 	= SalSysObjChildWndProcW;
563 				aWndClassEx.lpszClassName	= SAL_OBJECT_CHILDCLASSNAMEW;
564 				if ( RegisterClassExW( &aWndClassEx ) )
565 					pSalData->mbObjClassInit = TRUE;
566 			}
567 		}
568 		else
569 		{
570 			WNDCLASSEXA aWndClassEx;
571 			aWndClassEx.cbSize			= sizeof( aWndClassEx );
572 			aWndClassEx.style			= 0;
573 			aWndClassEx.lpfnWndProc 	= SalSysObjWndProcA;
574 			aWndClassEx.cbClsExtra		= 0;
575 			aWndClassEx.cbWndExtra		= SAL_OBJECT_WNDEXTRA;
576 			aWndClassEx.hInstance		= pSalData->mhInst;
577 			aWndClassEx.hIcon			= 0;
578 			aWndClassEx.hIconSm 		= 0;
579 			aWndClassEx.hCursor 		= LoadCursor( 0, IDC_ARROW );
580 			aWndClassEx.hbrBackground	= 0;
581 			aWndClassEx.lpszMenuName	= 0;
582 			aWndClassEx.lpszClassName	= SAL_OBJECT_CLASSNAMEA;
583 			if ( RegisterClassExA( &aWndClassEx ) )
584 			{
585 				// Wegen PlugIn's loeschen wir erstmal den Hintergrund
586 				aWndClassEx.cbWndExtra		= 0;
587 				aWndClassEx.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
588 				aWndClassEx.lpfnWndProc 	= SalSysObjChildWndProcA;
589 				aWndClassEx.lpszClassName	= SAL_OBJECT_CHILDCLASSNAMEA;
590 				if ( RegisterClassExA( &aWndClassEx ) )
591 					pSalData->mbObjClassInit = TRUE;
592 			}
593 		}
594 	}
595 
596 	if ( pSalData->mbObjClassInit )
597 	{
598 		WinSalObject* pObject = new WinSalObject;
599 
600         // #135235# Clip siblings of this
601         // SystemChildWindow. Otherwise, DXCanvas (using a hidden
602         // SystemChildWindow) clobbers applets/plugins during
603         // animations .
604         HWND hWnd = CreateWindowExA( 0, SAL_OBJECT_CLASSNAMEA, "",
605                                      WS_CHILD | WS_CLIPSIBLINGS, 0, 0, 0, 0,
606                                      pParent->mhWnd, 0,
607                                      pInst->mhInst, (void*)pObject );
608 
609 		HWND hWndChild = 0;
610         if ( hWnd )
611         {
612             // #135235# Explicitely stack SystemChildWindows in
613             // the order they're created - since there's no notion
614             // of zorder.
615             SetWindowPos(hWnd,HWND_TOP,0,0,0,0,
616                          SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOSIZE);
617             hWndChild = CreateWindowExA( 0, SAL_OBJECT_CHILDCLASSNAMEA, "",
618                                          WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
619                                          0, 0, 0, 0,
620                                          hWnd, 0,
621                                          pInst->mhInst, NULL );
622         }
623 
624 		if ( !hWndChild )
625 		{
626 			delete pObject;
627 			return NULL;
628 		}
629 
630 		if ( hWnd )
631 		{
632 			pObject->mhWnd 			= hWnd;
633 			pObject->mhWndChild		= hWndChild;
634 			pObject->maSysData.hWnd	= hWndChild;
635 			return pObject;
636 		}
637 	}
638 
639 	return NULL;
640 }
641 
642 // =======================================================================
643 
644 WinSalObject::WinSalObject()
645 {
646 	SalData* pSalData = GetSalData();
647 
648 	mhWnd			= 0;
649 	mhWndChild 		= 0;
650 	mhLastFocusWnd 	= 0;
651 	maSysData.nSize	= sizeof( SystemEnvData );
652 	mpStdClipRgnData	= NULL;
653     mbInterceptChildWindowKeyDown = sal_False;
654 
655 	// Insert object in objectlist
656 	mpNextObject = pSalData->mpFirstObject;
657 	pSalData->mpFirstObject = this;
658 }
659 
660 // -----------------------------------------------------------------------
661 
662 WinSalObject::~WinSalObject()
663 {
664 	SalData* pSalData = GetSalData();
665 
666 	// remove frame from framelist
667 	if ( this == pSalData->mpFirstObject )
668 	{
669 		pSalData->mpFirstObject = mpNextObject;
670 
671 		// Wenn letztes SalObject, dann Hook wieder entfernen
672 		if ( !pSalData->mpFirstObject )
673 			UnhookWindowsHookEx( pSalData->mhSalObjMsgHook );
674 	}
675 	else
676 	{
677 		WinSalObject* pTempObject = pSalData->mpFirstObject;
678 		while ( pTempObject->mpNextObject != this )
679 			pTempObject = pTempObject->mpNextObject;
680 
681 		pTempObject->mpNextObject = mpNextObject;
682 	}
683 
684 	// Cache-Daten zerstoeren
685 	if ( mpStdClipRgnData )
686 		delete mpStdClipRgnData;
687 
688 	HWND hWndParent = ::GetParent( mhWnd );
689 
690 	if ( mhWndChild )
691 		DestroyWindow( mhWndChild );
692 	if ( mhWnd )
693 		DestroyWindow( mhWnd );
694 
695 	// Palette wieder zuruecksetzen, wenn kein externes Child-Fenster
696 	// mehr vorhanden ist, da diese unsere Palette ueberschrieben haben
697 	// koennen
698 	if ( hWndParent &&
699 		 ::GetActiveWindow() == hWndParent &&
700 		 !GetWindow( hWndParent, GW_CHILD ) )
701 		ImplSendMessage( hWndParent, SAL_MSG_FORCEPALETTE, 0, 0 );
702 }
703 
704 // -----------------------------------------------------------------------
705 
706 void WinSalObject::ResetClipRegion()
707 {
708 	SetWindowRgn( mhWnd, 0, TRUE );
709 }
710 
711 // -----------------------------------------------------------------------
712 
713 sal_uInt16 WinSalObject::GetClipRegionType()
714 {
715 	return SAL_OBJECT_CLIP_INCLUDERECTS;
716 }
717 
718 // -----------------------------------------------------------------------
719 
720 void WinSalObject::BeginSetClipRegion( sal_uLong nRectCount )
721 {
722 	sal_uLong nRectBufSize = sizeof(RECT)*nRectCount;
723 	if ( nRectCount < SAL_CLIPRECT_COUNT )
724 	{
725 		if ( !mpStdClipRgnData )
726 			mpStdClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+(SAL_CLIPRECT_COUNT*sizeof(RECT))];
727 		mpClipRgnData = mpStdClipRgnData;
728 	}
729 	else
730 		mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize];
731 	mpClipRgnData->rdh.dwSize	  = sizeof( RGNDATAHEADER );
732 	mpClipRgnData->rdh.iType	  = RDH_RECTANGLES;
733 	mpClipRgnData->rdh.nCount	  = nRectCount;
734 	mpClipRgnData->rdh.nRgnSize  = nRectBufSize;
735 	SetRectEmpty( &(mpClipRgnData->rdh.rcBound) );
736 	mpNextClipRect 		  = (RECT*)(&(mpClipRgnData->Buffer));
737 	mbFirstClipRect		  = TRUE;
738 }
739 
740 // -----------------------------------------------------------------------
741 
742 void WinSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
743 {
744 	RECT*		pRect = mpNextClipRect;
745 	RECT*		pBoundRect = &(mpClipRgnData->rdh.rcBound);
746 	long		nRight = nX + nWidth;
747 	long		nBottom = nY + nHeight;
748 
749 	if ( mbFirstClipRect )
750 	{
751 		pBoundRect->left	= nX;
752 		pBoundRect->top 	= nY;
753 		pBoundRect->right	= nRight;
754 		pBoundRect->bottom	= nBottom;
755 		mbFirstClipRect = FALSE;
756 	}
757 	else
758 	{
759 		if ( nX < pBoundRect->left )
760 			pBoundRect->left = (int)nX;
761 
762 		if ( nY < pBoundRect->top )
763 			pBoundRect->top = (int)nY;
764 
765 		if ( nRight > pBoundRect->right )
766 			pBoundRect->right = (int)nRight;
767 
768 		if ( nBottom > pBoundRect->bottom )
769 			pBoundRect->bottom = (int)nBottom;
770 	}
771 
772 	pRect->left 	= (int)nX;
773 	pRect->top		= (int)nY;
774 	pRect->right	= (int)nRight;
775 	pRect->bottom	= (int)nBottom;
776 	mpNextClipRect++;
777 }
778 
779 // -----------------------------------------------------------------------
780 
781 void WinSalObject::EndSetClipRegion()
782 {
783 	HRGN hRegion;
784 
785 	// Aus den Region-Daten muessen wir jetzt eine ClipRegion erzeugen
786 	if ( mpClipRgnData->rdh.nCount == 1 )
787 	{
788 		RECT* pRect = &(mpClipRgnData->rdh.rcBound);
789 		hRegion = CreateRectRgn( pRect->left, pRect->top,
790 								 pRect->right, pRect->bottom );
791 	}
792 	else
793 	{
794 		sal_uLong nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER);
795 		hRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData );
796 		if ( mpClipRgnData != mpStdClipRgnData )
797 			delete [] (BYTE*)mpClipRgnData;
798 	}
799 
800 	DBG_ASSERT( hRegion, "SalObject::EndSetClipRegion() - Can't create ClipRegion" );
801 	SetWindowRgn( mhWnd, hRegion, TRUE );
802 }
803 
804 // -----------------------------------------------------------------------
805 
806 void WinSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
807 {
808 	sal_uLong nStyle = 0;
809 	sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
810 	if ( bVisible )
811 	{
812 		ShowWindow( mhWnd, SW_HIDE );
813 		nStyle |= SWP_SHOWWINDOW;
814 	}
815 	SetWindowPos( mhWnd, 0,
816 				  (int)nX, (int)nY, (int)nWidth, (int)nHeight,
817 				  SWP_NOZORDER | SWP_NOACTIVATE | nStyle );
818 }
819 
820 // -----------------------------------------------------------------------
821 
822 void WinSalObject::Show( sal_Bool bVisible )
823 {
824 	if ( bVisible )
825 		ShowWindow( mhWnd, SW_SHOWNORMAL );
826 	else
827 		ShowWindow( mhWnd, SW_HIDE );
828 }
829 
830 // -----------------------------------------------------------------------
831 
832 void WinSalObject::Enable( sal_Bool bEnable )
833 {
834 	EnableWindow( mhWnd, bEnable );
835 }
836 
837 // -----------------------------------------------------------------------
838 
839 void WinSalObject::GrabFocus()
840 {
841 	if ( mhLastFocusWnd &&
842 		 IsWindow( mhLastFocusWnd ) &&
843 		 ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) )
844 		::SetFocus( mhLastFocusWnd );
845 	else
846 		::SetFocus( mhWndChild );
847 }
848 
849 // -----------------------------------------------------------------------
850 
851 void WinSalObject::SetBackground()
852 {
853 }
854 
855 // -----------------------------------------------------------------------
856 
857 void WinSalObject::SetBackground( SalColor )
858 {
859 }
860 
861 // -----------------------------------------------------------------------
862 
863 const SystemEnvData* WinSalObject::GetSystemData() const
864 {
865 	return &maSysData;
866 }
867 
868 // -----------------------------------------------------------------------
869 
870 void WinSalObject::InterceptChildWindowKeyDown( sal_Bool bIntercept )
871 {
872     mbInterceptChildWindowKeyDown = bIntercept;
873 }
874 
875