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 #if defined(_MSC_VER) && (_MSC_VER > 1310)
24 #pragma warning(disable : 4917 4555)
25 #endif
26 
27 #include "docholder.hxx"
28 #include "syswinwrapper.hxx"
29 
30 /*
31  * CWindow::CWindow
32  * CWindow::~CWindow
33  *
34  * Constructor Parameters:
35  *  hInst           HINSTANCE of the task owning us.
36  */
37 
38 
39 using namespace winwrap;
40 
41 
42 #define HWWL_STRUCTURE                  0
43 
44 //Notification codes for WM_COMMAND messages
45 #define HWN_BORDERDOUBLECLICKED         1
46 #define CBHATCHWNDEXTRA                 (sizeof(LONG))
47 #define SZCLASSHATCHWIN                 TEXT("hatchwin")
48 #define SendCommand(hWnd, wID, wCode, hControl)                     \
49             SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(wID, wCode)    \
50                         , (LPARAM)hControl)
51 
52 
53 typedef CHatchWin *PCHatchWin;
54 
55 
56 void DrawShading(LPRECT prc, HDC hDC, UINT cWidth);
57 
58 
59 
CWindow(HINSTANCE hInst)60 winwrap::CWindow::CWindow(HINSTANCE hInst)
61 {
62     m_hInst=hInst;
63     m_hWnd=NULL;
64     return;
65 }
66 
~CWindow(void)67 winwrap::CWindow::~CWindow(void)
68 {
69     if (IsWindow(m_hWnd))
70         DestroyWindow(m_hWnd);
71 
72     return;
73 }
74 
75 
76 
77 /*
78  * CWindow::Window
79  *
80  * Purpose:
81  *  Returns the window handle associated with this object.
82  *
83  * Return Value:
84  *  HWND            Window handle for this object
85  */
86 
Window(void)87 HWND winwrap::CWindow::Window(void)
88 {
89     return m_hWnd;
90 }
91 
92 
93 
94 /*
95  * CWindow::Instance
96  *
97  * Purpose:
98  *  Returns the instance handle associated with this object.
99  *
100  * Return Value:
101  *  HINSTANCE       Instance handle of the module stored here.
102  */
103 
Instance(void)104 HINSTANCE winwrap::CWindow::Instance(void)
105 {
106     return m_hInst;
107 }
108 
109 
110 
111 
112 
113 //Hatch pattern brush bits
114 static WORD g_wHatchBmp[]={0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88};
115 
116 // void DrawShading(LPRECT, HDC, UINT);
117 
118 
119 /*
120  * HatchWindowRegister
121  *
122  * Purpose:
123  *  Registers the hatch window class for use with CHatchWin.
124  *
125  * Parameters:
126  *  hInst           HINSTANCE under which to register.
127  *
128  * Return Value:
129  *  BOOL            TRUE if successful, FALSE otherwise.
130  */
131 
HatchWindowRegister(HINSTANCE hInst)132 BOOL winwrap::HatchWindowRegister(HINSTANCE hInst)
133 {
134     WNDCLASS    wc;
135 
136     //Must have CS_DBLCLKS for border!
137     wc.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
138     wc.hInstance     = hInst;
139     wc.cbClsExtra    = 0;
140     wc.lpfnWndProc   = HatchWndProc;
141     wc.cbWndExtra    = CBHATCHWNDEXTRA;
142     wc.hIcon         = NULL;
143     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
144     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
145     wc.lpszMenuName  = NULL;
146     wc.lpszClassName = SZCLASSHATCHWIN;
147 
148     return RegisterClass(&wc);
149     return FALSE;
150 }
151 
152 
153 
154 
155 /*
156  * CHatchWin:CHatchWin
157  * CHatchWin::~CHatchWin
158  *
159  * Constructor Parameters:
160  *  hInst           HINSTANCE of the application we're in.
161  */
162 
CHatchWin(HINSTANCE hInst,const DocumentHolder * pDocHolder)163 CHatchWin::CHatchWin(HINSTANCE hInst,const DocumentHolder* pDocHolder)
164     : CWindow(hInst),
165       m_aTracker()
166 {
167     m_hWnd=NULL;
168     m_hWndKid=NULL;
169     m_hWndAssociate=NULL;
170     m_uID=0;
171 
172     m_dBorderOrg=GetProfileInt(TEXT("windows")
173                                , TEXT("OleInPlaceBorderWidth")
174                                , HATCHWIN_BORDERWIDTHDEFAULT);
175 
176     m_dBorder=m_dBorderOrg;
177     SetRect(&m_rcPos, 0, 0, 0, 0);
178     SetRect(&m_rcClip, 0, 0, 0, 0);
179 
180     m_pDocHolder = pDocHolder;
181     return;
182 }
183 
184 
~CHatchWin(void)185 CHatchWin::~CHatchWin(void)
186 {
187     /*
188      * Chances are this was already destroyed when a document
189      * was destroyed.
190      */
191     if (NULL!=m_hWnd && IsWindow(m_hWnd))
192         DestroyWindow(m_hWnd);
193 
194     return;
195 }
196 
197 
198 
199 /*
200  * CHatchWin::Init
201  *
202  * Purpose:
203  *  Instantiates a hatch window within a given parent with a
204  *  default rectangle.  This is not initially visible.
205  *
206  * Parameters:
207  *  hWndParent      HWND of the parent of this window
208  *  uID             UINT identifier for this window (send in
209  *                  notifications to associate window).
210  *  hWndAssoc       HWND of the initial associate.
211  *
212  * Return Value:
213  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
214  */
215 
Init(HWND hWndParent,UINT uID,HWND hWndAssoc)216 BOOL CHatchWin::Init(HWND hWndParent, UINT uID, HWND hWndAssoc)
217 {
218     m_hWndParent = hWndParent;
219 	m_hWnd=CreateWindowEx(
220 		WS_EX_NOPARENTNOTIFY, SZCLASSHATCHWIN
221 		, SZCLASSHATCHWIN, WS_CHILD | WS_CLIPSIBLINGS
222 		| WS_CLIPCHILDREN, 0, 0, 100, 100, hWndParent, (HMENU)uID
223         , m_hInst, this);
224 
225     m_uID=uID;
226     m_hWndAssociate=hWndAssoc;
227 
228     return (NULL!=m_hWnd);
229 }
230 
231 
SetTrans()232 void CHatchWin::SetTrans()
233 {
234     HRGN hrgn = CreateRectRgn(0,0,0,0);
235     SetWindowRgn(m_hWnd,hrgn,true);
236 }
237 
238 /*
239  * CHatchWin::HwndAssociateSet
240  * CHatchWin::HwndAssociateGet
241  *
242  * Purpose:
243  *  Sets (Set) or retrieves (Get) the associate window of the
244  *  hatch window.
245  *
246  * Parameters: (Set only)
247  *  hWndAssoc       HWND to set as the associate.
248  *
249  * Return Value:
250  *  HWND            Previous (Set) or current (Get) associate
251  *                  window.
252  */
253 
HwndAssociateSet(HWND hWndAssoc)254 HWND CHatchWin::HwndAssociateSet(HWND hWndAssoc)
255 {
256     HWND    hWndT=m_hWndAssociate;
257 
258     m_hWndAssociate=hWndAssoc;
259     return hWndT;
260 }
261 
262 
HwndAssociateGet(void)263 HWND CHatchWin::HwndAssociateGet(void)
264 {
265     return m_hWndAssociate;
266 }
267 
268 
269 /*
270  * CHatchWin::RectsSet
271  *
272  * Purpose:
273  *  Changes the size and position of the hatch window and the child
274  *  window within it using a position rectangle for the child and
275  *  a clipping rectangle for the hatch window and child.  The hatch
276  *  window occupies prcPos expanded by the hatch border and clipped
277  *  by prcClip.  The child window is fit to prcPos to give the
278  *  proper scaling, but it clipped to the hatch window which
279  *  therefore clips it to prcClip without affecting the scaling.
280  *
281  * Parameters:
282  *  prcPos          LPRECT providing the position rectangle.
283  *  prcClip         LPRECT providing the clipping rectangle.
284  *
285  * Return Value:
286  *  None
287  */
288 
RectsSet(LPRECT prcPos,LPRECT prcClip)289 void CHatchWin::RectsSet(LPRECT prcPos, LPRECT prcClip)
290 {
291     RECT    rc;
292     RECT    rcPos;
293 
294     m_rcPos=*prcPos;
295     m_rcClip=*prcClip;
296 
297     //Calculate the rectangle for the hatch window, then clip it.
298     rcPos=*prcPos;
299     InflateRect(&rcPos, m_dBorder, m_dBorder);
300     IntersectRect(&rc, &rcPos, prcClip);
301 
302     SetWindowPos(m_hWnd, NULL, rc.left, rc.top, rc.right-rc.left
303                  , rc.bottom-rc.top, SWP_NOZORDER | SWP_NOACTIVATE);
304 
305     /*
306      * Set the rectangle of the child window to be at m_dBorder
307      * from the top and left but with the same size as prcPos
308      * contains.  The hatch window will clip it.
309      */
310 //     SetWindowPos(m_hWndKid, NULL, rcPos.left-rc.left+m_dBorder
311 //                  , rcPos.top-rc.top+m_dBorder, prcPos->right-prcPos->left
312 //                  , prcPos->bottom-prcPos->top, SWP_NOZORDER | SWP_NOACTIVATE);
313 
314     RECT newRC;
315     GetClientRect(m_hWnd,&newRC);
316     m_aTracker = Tracker(
317         &newRC,
318         Tracker::hatchInside |
319         Tracker::hatchedBorder |
320         Tracker::resizeInside
321     );
322 
323     return;
324 }
325 
326 
327 
328 /*
329  * CHatchWin::ChildSet
330  *
331  * Purpose:
332  *  Assigns a child window to this hatch window.
333  *
334  * Parameters:
335  *  hWndKid         HWND of the child window.
336  *
337  * Return Value:
338  *  None
339  */
340 
ChildSet(HWND hWndKid)341 void CHatchWin::ChildSet(HWND hWndKid)
342 {
343     m_hWndKid=hWndKid;
344 
345     if (NULL!=hWndKid)
346     {
347         SetParent(hWndKid, m_hWnd);
348 
349         //Insure this is visible when the hatch window becomes visible.
350         ShowWindow(hWndKid, SW_SHOW);
351     }
352 
353     return;
354 }
355 
356 
357 
358 /*
359  * CHatchWin::ShowHatch
360  *
361  * Purpose:
362  *  Turns hatching on and off; turning the hatching off changes
363  *  the size of the window to be exactly that of the child, leaving
364  *  everything else the same.  The result is that we don't have
365  *  to turn off drawing because our own WM_PAINT will never be
366  *  called.
367  *
368  * Parameters:
369  *  fHatch          BOOL indicating to show (TRUE) or hide (FALSE)
370                     the hatching.
371  *
372  * Return Value:
373  *  None
374  */
375 
ShowHatch(BOOL fHatch)376 void CHatchWin::ShowHatch(BOOL fHatch)
377 {
378     /*
379      * All we have to do is set the border to zero and
380      * call SetRects again with the last rectangles the
381      * child sent to us.
382      */
383     m_dBorder=fHatch ? m_dBorderOrg : 0;
384     RectsSet(&m_rcPos, &m_rcClip);
385     return;
386 }
387 
388 
389 
390 /*
391  * HatchWndProc
392  *
393  * Purpose:
394  *  Standard window procedure for the Hatch Window
395  */
396 
HatchWndProc(HWND hWnd,UINT iMsg,WPARAM wParam,LPARAM lParam)397 LRESULT APIENTRY winwrap::HatchWndProc(
398     HWND hWnd, UINT iMsg
399     , WPARAM wParam, LPARAM lParam)
400 {
401     PCHatchWin  phw;
402     HDC         hDC;
403     PAINTSTRUCT ps;
404 
405     phw=(PCHatchWin)GetWindowLong(hWnd, HWWL_STRUCTURE);
406     POINT ptMouse;
407 
408     switch (iMsg)
409     {
410         case WM_CREATE:
411             phw=(PCHatchWin)((LPCREATESTRUCT)lParam)->lpCreateParams;
412             SetWindowLong(hWnd, HWWL_STRUCTURE, (LONG)phw);
413             break;
414         case WM_PAINT:
415             hDC=BeginPaint(hWnd,&ps);
416             //Always draw the hatching.
417             phw->m_aTracker.Draw(hDC);
418             EndPaint(hWnd,&ps);
419             break;
420         case WM_LBUTTONDOWN:
421             GetCursorPos(&ptMouse);
422             ScreenToClient(hWnd,&ptMouse);
423 
424             // track in case we have to
425             if(phw->m_aTracker.Track(hWnd,ptMouse,FALSE,GetParent(hWnd)))
426             {
427                 RECT aRect = phw->m_aTracker.m_rect;
428                 TransformRect(&aRect,hWnd,GetParent(hWnd));
429                 phw->m_pDocHolder->OnPosRectChanged(&aRect);
430             }
431             break;
432 		case WM_LBUTTONUP:
433         case WM_MOUSEMOVE:
434             GetCursorPos(&ptMouse);
435             ScreenToClient(hWnd,&ptMouse);
436             phw->m_aTracker.SetCursor(hWnd,HTCLIENT);
437             break;
438         case WM_SETFOCUS:
439             //We need this since the container will SetFocus to us.
440             if (NULL!=phw->m_hWndKid)
441                 SetFocus(phw->m_hWndKid);
442 
443             break;
444         case WM_LBUTTONDBLCLK:
445             /*
446              * If the double click was within m_dBorder of an
447              * edge, send the HWN_BORDERDOUBLECLICKED notification.
448              *
449              * Because we're always sized just larger than our child
450              * window by the border width, we can only *get* this
451              * message when the mouse is on the border.  So we can
452              * just send the notification.
453              */
454             if (NULL!=phw->m_hWndAssociate)
455             {
456                 SendCommand(phw->m_hWndAssociate, phw->m_uID
457                             , HWN_BORDERDOUBLECLICKED, hWnd);
458             }
459 
460             break;
461         default:
462             return DefWindowProc(hWnd, iMsg, wParam, lParam);
463     }
464 
465     return 0L;
466 }
467 
468 // Fix strange warnings about some
469 // ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
470 // warning C4505: 'xxx' : unreferenced local function has been removed
471 #if defined(_MSC_VER)
472 #pragma warning(disable: 4505)
473 #endif
474