0023712: Remove dependency on Aspect_GraphicDevice from Aspect_Window
[occt.git] / src / WNT / WNT_Window.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 // include windows.h first to have all definitions available
20 #include <windows.h>
21
22 //                GG 07/03/00 Add MMSize() method
23
24 #include <WNT_Window.ixx>
25
26 #include <Image_AlienPixMap.hxx>
27 #include <Aspect_Convert.hxx>
28
29 #include <stdio.h>
30 extern "C" void _debug_break ( char* );
31 //************************************************************************//
32 //***//
33 // callback function to manage window's background
34 extern LRESULT CALLBACK WNT_WndProc (
35                          HWND, UINT, WPARAM, LPARAM
36                         );
37
38 WNT_Window::WNT_Window (const Standard_CString           theTitle,
39                         const Handle(WNT_WClass)&        theClass,
40                         const WNT_Dword&                 theStyle,
41                         const Standard_Integer           thePxLeft,
42                         const Standard_Integer           thePxTop,
43                         const Standard_Integer           thePxWidth,
44                         const Standard_Integer           thePxHeight,
45                         const Quantity_NameOfColor       theBackColor,
46                         const Aspect_Handle              theParent,
47                         const Aspect_Handle              theMenu,
48                         const Standard_Address           theClientStruct)
49 : Aspect_Window(),
50   aXLeft (thePxLeft),
51   aYTop (thePxTop),
52   aXRight (thePxLeft + thePxWidth),
53   aYBottom (thePxTop + thePxHeight),
54   myWClass (theClass)
55 {
56   ZeroMemory (&myExtraData, sizeof (WNT_WindowData));
57   DWORD dwStyle = theStyle;
58
59   if (thePxWidth <= 0 || thePxHeight <= 0)
60   {
61     Aspect_WindowDefinitionError::Raise ("Coordinate(s) out of range");
62   }
63
64   if (theParent && !(theStyle & WS_CHILD))
65   {
66     dwStyle |= WS_CHILD | WS_CLIPSIBLINGS;
67   }
68   else if (!theParent && !(theStyle & WS_CLIPCHILDREN))
69   {
70     dwStyle |= WS_CLIPCHILDREN;
71   }
72
73   // include decorations in the window dimensions
74   // to reproduce same behaviour of Xw_Window.
75   RECT aRect;
76   aRect.top    = aYTop;
77   aRect.bottom = aYBottom;
78   aRect.left   = aXLeft;
79   aRect.right  = aXRight;
80   AdjustWindowRect (&aRect, dwStyle, theMenu != NULL ? TRUE : FALSE);
81   aXLeft   = aRect.left;
82   aYTop    = aRect.top;
83   aXRight  = aRect.right;
84   aYBottom = aRect.bottom;
85
86   myHWindow = CreateWindow (
87               myWClass->Name(),                 // window's class name
88               theTitle,                         // window's name
89               dwStyle,                          // window's style
90               aXLeft, aYTop,                    // window's coordinates
91               (aXRight - aXLeft), (aYBottom - aYTop),
92               (HWND )theParent,                 // window's parent
93               (HMENU )theMenu,                  // window's menu
94               (HINSTANCE )myWClass->Instance(), // application's instance
95               theClientStruct);                 // pointer to CLIENTCREATESTRUCT
96   if (!myHWindow)
97   {
98     Aspect_WindowDefinitionError::Raise ("Unable to create window");
99   }
100
101   myHParentWindow = theParent;
102   SetBackground (theBackColor);
103
104   myUsrData = (Standard_Address )SetWindowLongPtr ((HWND )myHWindow, GWLP_USERDATA, (LONG_PTR )&myExtraData);
105
106   myExtraData.WNT_Window_Ptr = (void* )this;
107
108   SetFlags (WDF_NOERASEBKGRND);
109 }
110
111 //***//
112 //************************* Constructor **********************************//
113 //***//
114 WNT_Window :: WNT_Window (
115                const Aspect_Handle                aHandle,
116                const Quantity_NameOfColor         aBackColor
117               ) : Aspect_Window()
118 {
119   doCreate (aHandle, aBackColor);
120
121   /* Bug OCC20596 */
122   SetFlags(WDF_NOERASEBKGRND);
123
124 }  // end constructor
125 //***//
126 //************************* Constructor **********************************//
127 //***//
128 WNT_Window :: WNT_Window (
129                const Standard_Integer             aPart1,
130                const Standard_Integer             aPart2,
131                const Quantity_NameOfColor         aBackColor
132               ) : Aspect_Window()
133 {
134   Aspect_Handle aHandle = ( Aspect_Handle )(  ( aPart1 << 16 ) + aPart2  );
135
136   doCreate (aHandle, aBackColor);
137
138   /* Bug OCC20596 */
139   SetFlags(WDF_NOERASEBKGRND);
140
141 }  // end constructor
142 //***//
143 //***************************** Destroy **********************************//
144 //***//
145 void WNT_Window :: Destroy ()
146 {
147   if (myHWindow)
148   {
149     if (myUsrData != Standard_Address(-1))
150     {
151       SetWindowLongPtr ((HWND )myHWindow, GWLP_USERDATA, (LONG_PTR )myUsrData);
152     }
153
154     if (!( myExtraData.dwFlags & WDF_FOREIGN))
155     {
156       DestroyWindow ((HWND )myHWindow);
157     }
158   }  // end if
159 }  // end WNT_Window :: Destroy
160
161 //**************************** SetCursor *********************************//
162 //***//
163 void WNT_Window :: SetCursor ( const Aspect_Handle aCursor ) const {
164
165 #ifndef _WIN64
166  SetClassLong (  ( HWND )myHWindow, GCL_HCURSOR, ( LONG )aCursor  );
167 #else
168  SetClassLong (  ( HWND )myHWindow, GCLP_HCURSOR, ( LONG )aCursor  );
169 #endif
170
171 }  // end WNT_Window :: SetCursor
172
173 //***//
174 //***************************** IsMapped *********************************//
175 //***//
176 Standard_Boolean WNT_Window :: IsMapped () const {
177   if (IsVirtual()) {
178     return Standard_True;
179   }
180
181   WINDOWPLACEMENT wp;
182
183   wp.length = sizeof ( WINDOWPLACEMENT );
184   GetWindowPlacement (  ( HWND )myHWindow, &wp  );
185
186   return !(  wp.showCmd == SW_HIDE || wp.showCmd == SW_MINIMIZE );
187 }  // WNT_Window :: IsMapped
188
189 //***//
190 //***************************** Map (1) **********************************//
191 //***//
192 void WNT_Window :: Map () const {
193   if (IsVirtual()) {
194     return;
195   }
196   Map ( SW_SHOW );
197 }  // end WNT_Window :: Map
198
199 //***//
200 //***************************** Map (2) **********************************//
201 //***//
202 void WNT_Window :: Map ( const Standard_Integer aMapMode ) const {
203   if (IsVirtual()) {
204     return;
205   }
206   ShowWindow (  ( HWND )myHWindow, aMapMode  );
207   UpdateWindow (  ( HWND )myHWindow  );
208
209 }  // end WNT_Window :: Map
210
211 //***//
212 //**************************** Unmap *************************************//
213 //***//
214 void WNT_Window :: Unmap () const {
215
216  Map ( SW_HIDE );
217
218 }  // end WNT_Window :: Unmap
219
220 //***//
221 //**************************** DoResize **********************************//
222 //***//
223 Aspect_TypeOfResize WNT_Window :: DoResize () const
224 {
225   int                 mask = 0;
226   Aspect_TypeOfResize mode = Aspect_TOR_UNKNOWN;
227   WINDOWPLACEMENT     wp;
228
229   wp.length = sizeof ( WINDOWPLACEMENT );
230   GetWindowPlacement (  ( HWND )myHWindow, &wp  );
231
232   if (wp.showCmd != SW_SHOWMINIMIZED)
233   {
234     if (Abs (wp.rcNormalPosition.left   - aXLeft  ) > 2) mask |= 1;
235     if (Abs (wp.rcNormalPosition.right  - aXRight ) > 2) mask |= 2;
236     if (Abs (wp.rcNormalPosition.top    - aYTop   ) > 2) mask |= 4;
237     if (Abs (wp.rcNormalPosition.bottom - aYBottom) > 2) mask |= 8;
238
239     switch (mask)
240     {
241       case 0:
242         mode = Aspect_TOR_NO_BORDER;
243         break;
244       case 1:
245         mode = Aspect_TOR_LEFT_BORDER;
246         break;
247       case 2:
248         mode = Aspect_TOR_RIGHT_BORDER;
249         break;
250       case 4:
251         mode = Aspect_TOR_TOP_BORDER;
252         break;
253       case 5:
254         mode = Aspect_TOR_LEFT_AND_TOP_BORDER;
255         break;
256       case 6:
257         mode = Aspect_TOR_TOP_AND_RIGHT_BORDER;
258         break;
259       case 8:
260         mode = Aspect_TOR_BOTTOM_BORDER;
261         break;
262       case 9:
263         mode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER;
264         break;
265       case 10:
266         mode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER;
267         break;
268       default:
269         break;
270     }  // end switch
271
272     *((Standard_Integer* )&aXLeft  ) = wp.rcNormalPosition.left;
273     *((Standard_Integer* )&aXRight ) = wp.rcNormalPosition.right;
274     *((Standard_Integer* )&aYTop   ) = wp.rcNormalPosition.top;
275     *((Standard_Integer* )&aYBottom) = wp.rcNormalPosition.bottom;
276   }
277
278   return mode;
279
280 }  // end WNT_Window :: DoResize
281
282 //***//
283 //**************************** DoMapping **********************************//
284 //***//
285 Standard_Boolean WNT_Window :: DoMapping () const {
286 // DO nothing on WNT.
287   return Standard_True;
288 }
289
290 static Standard_Boolean ConvertBitmap (HBITMAP       theHBitmap,
291                                        Image_PixMap& thePixMap)
292 {
293   // Get informations about the bitmap
294   BITMAP aBitmap;
295   if (GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap) == 0)
296   {
297     return Standard_False;
298   }
299
300   const Standard_Size aSizeRowBytes = Standard_Size(aBitmap.bmWidth) * 4;
301   if (!thePixMap.InitTrash (Image_PixMap::ImgBGR32, Standard_Size(aBitmap.bmWidth), Standard_Size(aBitmap.bmHeight), aSizeRowBytes))
302   {
303     return Standard_False;
304   }
305   thePixMap.SetTopDown (false);
306
307   // Setup image data
308   BITMAPINFOHEADER aBitmapInfo;
309   memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
310   aBitmapInfo.biSize        = sizeof(BITMAPINFOHEADER);
311   aBitmapInfo.biWidth       = aBitmap.bmWidth;
312   aBitmapInfo.biHeight      = aBitmap.bmHeight; // positive means bottom-up!
313   aBitmapInfo.biPlanes      = 1;
314   aBitmapInfo.biBitCount    = 32; // use 32bit for automatic word-alignment per row
315   aBitmapInfo.biCompression = BI_RGB;
316
317   // Copy the pixels
318   HDC aDC = GetDC (NULL);
319   Standard_Boolean isSuccess = GetDIBits (aDC, theHBitmap,
320                                           0,                           // first scan line to set
321                                           aBitmap.bmHeight,            // number of scan lines to copy
322                                           thePixMap.ChangeData(),      // array for bitmap bits
323                                           (LPBITMAPINFO )&aBitmapInfo, // bitmap data info
324                                           DIB_RGB_COLORS) != 0;
325   ReleaseDC (NULL, aDC);
326   return isSuccess;
327 }
328
329 //***//
330 //******************************* Ratio **********************************//
331 //***//
332 Quantity_Ratio WNT_Window :: Ratio () const {
333
334  RECT r;
335
336  GetClientRect (  ( HWND )myHWindow, &r  );
337
338  return ( Quantity_Ratio )(  ( Quantity_Ratio )r.right / ( Quantity_Ratio )r.bottom  );
339
340 }  // end WNT_Window :: Ratio
341
342 //***//
343 //**************************** Position (2) ******************************//
344 //***//
345 void WNT_Window :: Position (
346                     Standard_Integer& X1, Standard_Integer& Y1,
347                     Standard_Integer& X2, Standard_Integer& Y2
348                    ) const {
349
350  POINT ptl, ptr;
351  RECT  r;
352
353  GetClientRect (  ( HWND )myHWindow, &r  );
354
355  ptl.x = ptl.y = 0;
356  ClientToScreen (  ( HWND )myHWindow, &ptl  );
357  ptr.x = r.right;
358  ptr.y = r.bottom;
359  ClientToScreen (  ( HWND )myHWindow, &ptr  );
360
361  if ( myHParentWindow ) {
362
363   ScreenToClient (      ( HWND )myHParentWindow, &ptl  );
364   ScreenToClient (  ( HWND )myHParentWindow, &ptr  );
365
366  }  // end if
367
368  X1 = ptl.x;
369  X2 = ptr.x;
370  Y1 = ptl.y;
371  Y2 = ptr.y;
372
373 }  // end WNT_Window :: Position
374
375 //***//
376 //******************************* Size (2) *******************************//
377 //***//
378 void WNT_Window :: Size (
379                     Standard_Integer& Width, Standard_Integer& Height
380                    ) const {
381
382  RECT r;
383
384  GetClientRect (  ( HWND )myHWindow, &r  );
385
386  Width  = r.right;
387  Height = r.bottom;
388
389 }  // end WNT_Window :: Size
390
391 //***//
392 //******************************* SetPos *********************************//
393 //***//
394 void WNT_Window :: SetPos (
395                     const Standard_Integer X,  const Standard_Integer Y,
396                     const Standard_Integer X1, const Standard_Integer Y1
397                    ) {
398
399  aXLeft   = X;
400  aYTop    = Y;
401  aXRight  = X1;
402  aYBottom = Y1;
403
404 }  // end WNT_Window :: SetPos
405
406 //***//
407 //**************************** SetFlags **********************************//
408 //***//
409 void WNT_Window :: SetFlags ( const Standard_Integer aFlags ) {
410
411  myExtraData.dwFlags |= aFlags;
412
413 }  // end WNT_Window :: SetFlags
414
415 //***//
416 //*************************** ResetFlags *********************************//
417 //***//
418 void WNT_Window :: ResetFlags ( const Standard_Integer aFlags ) {
419
420  myExtraData.dwFlags &= ~aFlags;
421
422 }  // end WNT_Window :: ResetFlags
423
424 //***//
425 //*************************** doCreate **********************************//
426 //***//
427 void WNT_Window :: doCreate (
428                     const Aspect_Handle                aHandle,
429                     const Quantity_NameOfColor         aBackColor
430                    )
431 {
432   LONG            uData;
433   WINDOWPLACEMENT wp;
434
435   ZeroMemory (&myExtraData, sizeof (WNT_WindowData));
436
437   myHWindow        = aHandle;
438   myHParentWindow  = GetParent ((HWND )aHandle);
439   uData            = GetWindowLongPtr ((HWND )aHandle, GWLP_USERDATA);
440   myUsrData        = Standard_Address(-1);
441
442   SetBackground (aBackColor);
443
444   myExtraData.WNT_Window_Ptr = (void* )this;
445
446   if (uData != (LONG )&myExtraData)
447   {
448     myUsrData = (Standard_Address )SetWindowLongPtr ((HWND )myHWindow, GWLP_USERDATA, (LONG_PTR )&myExtraData);
449   }
450
451   myExtraData.dwFlags = WDF_FOREIGN;
452
453   wp.length = sizeof (WINDOWPLACEMENT);
454   GetWindowPlacement ((HWND )myHWindow, &wp);
455
456   aXLeft   = wp.rcNormalPosition.left;
457   aYTop    = wp.rcNormalPosition.top;
458   aXRight  = wp.rcNormalPosition.right;
459   aYBottom = wp.rcNormalPosition.bottom;
460 }  // end WNT_Window :: doCreate