xref: /AOO41X/main/vcl/win/source/window/salobj.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
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 
ImplIsSysWindowOrChild(HWND hWndParent,HWND hWndChild)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 
ImplFindSalObject(HWND hWndChild)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 
ImplFindSalObjectFrame(HWND hWnd)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 
ImplInterceptChildWindowKeyDown(MSG & rMsg)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 
SalSysMsgProc(int nCode,WPARAM wParam,LPARAM lParam)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 
ImplSalPreDispatchMsg(MSG * pMsg)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 
ImplSalPostDispatchMsg(MSG * pMsg,LRESULT)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 
SalSysObjWndProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam,int & rDef)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 
SalSysObjWndProcA(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)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 
SalSysObjWndProcW(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)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 
SalSysObjChildWndProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam,int & rDef)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 
SalSysObjChildWndProcA(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)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 
SalSysObjChildWndProcW(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)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 
ImplSalCreateObject(WinSalInstance * pInst,WinSalFrame * pParent)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 
WinSalObject()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 
~WinSalObject()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 
ResetClipRegion()706 void WinSalObject::ResetClipRegion()
707 {
708     SetWindowRgn( mhWnd, 0, TRUE );
709 }
710 
711 // -----------------------------------------------------------------------
712 
GetClipRegionType()713 sal_uInt16 WinSalObject::GetClipRegionType()
714 {
715     return SAL_OBJECT_CLIP_INCLUDERECTS;
716 }
717 
718 // -----------------------------------------------------------------------
719 
BeginSetClipRegion(sal_uLong nRectCount)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 
UnionClipRegion(long nX,long nY,long nWidth,long nHeight)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 
EndSetClipRegion()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 
SetPosSize(long nX,long nY,long nWidth,long nHeight)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 
Show(sal_Bool bVisible)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 
Enable(sal_Bool bEnable)832 void WinSalObject::Enable( sal_Bool bEnable )
833 {
834     EnableWindow( mhWnd, bEnable );
835 }
836 
837 // -----------------------------------------------------------------------
838 
GrabFocus()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 
SetBackground()851 void WinSalObject::SetBackground()
852 {
853 }
854 
855 // -----------------------------------------------------------------------
856 
SetBackground(SalColor)857 void WinSalObject::SetBackground( SalColor )
858 {
859 }
860 
861 // -----------------------------------------------------------------------
862 
GetSystemData() const863 const SystemEnvData* WinSalObject::GetSystemData() const
864 {
865     return &maSysData;
866 }
867 
868 // -----------------------------------------------------------------------
869 
InterceptChildWindowKeyDown(sal_Bool bIntercept)870 void WinSalObject::InterceptChildWindowKeyDown( sal_Bool bIntercept )
871 {
872     mbInterceptChildWindowKeyDown = bIntercept;
873 }
874 
875