source: trunk/src/user32/win32wbasepos.cpp@ 7801

Last change on this file since 7801 was 7801, checked in by sandervl, 24 years ago

message handling changes

File size: 12.7 KB
Line 
1/* $Id: win32wbasepos.cpp,v 1.27 2002-02-05 17:59:01 sandervl Exp $ */
2/*
3 * Win32 Window Base Class for OS/2 (nonclient/position methods)
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 *
8 * Parts based on Wine Windows code (windows\win.c, windows\nonclient.c)
9 *
10 * Copyright 1993, 1994 Alexandre Julliard
11 *
12 * TODO: Not thread/process safe
13 *
14 * Wine code based on build 990815
15 *
16 * Project Odin Software License can be found in LICENSE.TXT
17 *
18 */
19#include <os2win.h>
20#include <win.h>
21#include <stdlib.h>
22#include <string.h>
23#include <stdarg.h>
24#include <assert.h>
25#include <misc.h>
26#include <win32wbase.h>
27#include <spy.h>
28#include "wndmsg.h"
29#include "oslibwin.h"
30#include "oslibutil.h"
31#include "oslibgdi.h"
32#include "oslibres.h"
33#include "oslibdos.h"
34#include "syscolor.h"
35#include "win32wndhandle.h"
36#include "dc.h"
37#include "win32wdesktop.h"
38#include <win\hook.h>
39
40#define DBG_LOCALLOG DBG_win32wbasepos
41#include "dbglocal.h"
42
43/*******************************************************************
44 * GetMinMaxInfo
45 *
46 * Get the minimized and maximized information for a window.
47 */
48void Win32BaseWindow::GetMinMaxInfo(POINT *maxSize, POINT *maxPos,
49 POINT *minTrack, POINT *maxTrack )
50{
51 MINMAXINFO MinMax;
52 INT xinc, yinc;
53
54 /* Compute default values */
55 MinMax.ptMaxPosition.x = 0;
56 MinMax.ptMaxPosition.y = 0;
57
58 if(!(getStyle() & (WS_POPUP | WS_CHILD))) {
59 RECT rect;
60 OSLibWinGetMaxPosition(getOS2FrameWindowHandle(), &rect);
61 MinMax.ptMaxPosition.x = rect.left;
62 MinMax.ptMaxPosition.y = rect.top;
63
64 MinMax.ptMaxSize.x = rect.right - rect.left;
65 MinMax.ptMaxSize.y = rect.bottom - rect.top;
66 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
67 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
68 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
69 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
70 }
71 else {
72 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
73 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
74 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
75 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
76 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
77 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
78 }
79
80 if (HAS_DLGFRAME( dwStyle, dwExStyle ))
81 {
82 xinc = GetSystemMetrics(SM_CXDLGFRAME);
83 yinc = GetSystemMetrics(SM_CYDLGFRAME);
84 }
85 else
86 {
87 xinc = yinc = 0;
88 if (HAS_THICKFRAME(dwStyle, dwExStyle))
89 {
90 xinc += GetSystemMetrics(SM_CXFRAME);
91 yinc += GetSystemMetrics(SM_CYFRAME);
92 }
93 //SvL: Wine has no 'else', but I'm seeing different behaviour in NT
94 // and it doesn't make much sense either as a window can have
95 // only one kind of border (see drawing code)
96 else
97 if (dwStyle & WS_BORDER)
98 {
99 xinc += GetSystemMetrics(SM_CXBORDER);
100 yinc += GetSystemMetrics(SM_CYBORDER);
101 }
102 }
103 MinMax.ptMaxSize.x += 2 * xinc;
104 MinMax.ptMaxSize.y += 2 * yinc;
105
106#if 0
107 lpPos = (LPINTERNALPOS)GetPropA( hwndSelf, atomInternalPos );
108 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
109 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
110 else
111 {
112#endif
113 MinMax.ptMaxPosition.x -= xinc;
114 MinMax.ptMaxPosition.y -= yinc;
115// }
116
117 SendMessageA(getWindowHandle(), WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
118
119 /* Some sanity checks */
120
121 dprintf(("GetMinMaxInfo: %ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
122 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
123 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
124 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
125 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y));
126 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
127 MinMax.ptMinTrackSize.x );
128 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
129 MinMax.ptMinTrackSize.y );
130
131 if (maxSize) *maxSize = MinMax.ptMaxSize;
132 if (maxPos) *maxPos = MinMax.ptMaxPosition;
133 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
134 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
135}
136/***********************************************************************
137 * WINPOS_SendNCCalcSize
138 *
139 * Send a WM_NCCALCSIZE message to a window.
140 * All parameters are read-only except newClientRect.
141 * oldWindowRect, oldClientRect and winpos must be non-NULL only
142 * when calcValidRect is TRUE.
143 */
144LONG Win32BaseWindow::SendNCCalcSize(BOOL calcValidRect, RECT *newWindowRect,
145 RECT *oldWindowRect,
146 RECT *oldClientRect, WINDOWPOS *winpos,
147 RECT *newClientRect )
148{
149 NCCALCSIZE_PARAMS params;
150 WINDOWPOS winposCopy;
151 LONG result = 0;
152
153 /* Send WM_NCCALCSIZE message to get new client area */
154 params.rgrc[0] = *newWindowRect;
155 if(calcValidRect)
156 {
157 winposCopy = *winpos;
158 params.rgrc[1] = *oldWindowRect;
159 params.rgrc[2] = *oldClientRect;
160 //client rectangel must be in parent coordinates
161 OffsetRect(&params.rgrc[2], rectWindow.left, rectWindow.top);
162
163 params.lppos = &winposCopy;
164 }
165 result = SendMessageA(getWindowHandle(), WM_NCCALCSIZE, calcValidRect, (LPARAM)&params );
166
167 /* If the application send back garbage, ignore it */
168 if(params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
169 {
170 *newClientRect = params.rgrc[0];
171 //client rectangle now in parent coordinates; convert to 'frame' coordinates
172 OffsetRect(newClientRect, -rectWindow.left, -rectWindow.top);
173 }
174
175 /* FIXME: WVR_ALIGNxxx */
176 if(newClientRect->left != rectClient.left || newClientRect->top != rectClient.top)
177 winpos->flags &= ~SWP_NOCLIENTMOVE;
178
179 if((newClientRect->right - newClientRect->left != rectClient.right - rectClient.left) ||
180 (newClientRect->bottom - newClientRect->top != rectClient.bottom - rectClient.top))
181 winpos->flags &= ~SWP_NOCLIENTSIZE;
182
183 return result;
184}
185/***********************************************************************
186 * WINPOS_HandleWindowPosChanging
187 *
188 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
189 */
190LONG Win32BaseWindow::HandleWindowPosChanging(WINDOWPOS *winpos)
191{
192 POINT maxSize;
193 if (winpos->flags & SWP_NOSIZE) return 0;
194
195 if ((dwStyle & WS_THICKFRAME) ||
196 ((dwStyle & (WS_POPUP | WS_CHILD)) == 0))
197 {
198 GetMinMaxInfo( &maxSize, NULL, NULL, NULL );
199 winpos->cx = MIN( winpos->cx, maxSize.x );
200 winpos->cy = MIN( winpos->cy, maxSize.y );
201 }
202 return 0;
203}
204/***********************************************************************
205 * WINPOS_FindIconPos
206 *
207 * Find a suitable place for an iconic window.
208 */
209static void WINPOS_FindIconPos( HWND hwnd, POINT &pt )
210{
211 RECT rectParent;
212 int x, y, xspacing, yspacing;
213 HWND hwndChild, hwndParent;
214
215 hwndParent = GetParent(hwnd);
216 if(hwndParent == 0) {
217 dprintf(("WINPOS_FindIconPos: no parent found for window %x", hwnd));
218 return;
219 }
220
221 GetClientRect(hwndParent, &rectParent );
222 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
223 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
224 return; /* The icon already has a suitable position */
225
226 xspacing = GetSystemMetrics(SM_CXICONSPACING);
227 yspacing = GetSystemMetrics(SM_CYICONSPACING);
228
229 y = rectParent.bottom;
230 for (;;)
231 {
232 x = rectParent.left;
233 do
234 {
235 /* Check if another icon already occupies this spot */
236 hwndChild = GetWindow(hwndParent, GW_CHILD);
237
238 while(hwndChild)
239 {
240 Win32BaseWindow *child = NULL;
241 RECT *pRectWindow;
242
243 child = Win32BaseWindow::GetWindowFromHandle(hwndChild);
244 if(!child) {
245 dprintf(("ERROR: WINPOS_FindIconPos, child %x not found", hwndChild));
246 return;
247 }
248 if ((child->getStyle() & WS_MINIMIZE) && (child->getWindowHandle() != hwnd))
249 {
250 pRectWindow = child->getWindowRect();
251 if ((pRectWindow->left < x + xspacing) &&
252 (pRectWindow->right >= x) &&
253 (pRectWindow->top <= y) &&
254 (pRectWindow->bottom > y - yspacing))
255 break; /* There's a window in there */
256 }
257 RELEASE_WNDOBJ(child);
258 hwndChild = GetWindow(hwndChild, GW_HWNDNEXT);
259 }
260
261 if (!hwndChild) /* No window was found, so it's OK for us */
262 {
263 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
264 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
265 return;
266 }
267 x += xspacing;
268 } while(x <= rectParent.right-xspacing);
269
270 y -= yspacing;
271 }
272}
273/******************************************************************************
274 * WINPOS_MinMaximize
275 *
276 * Fill in lpRect and return additional flags to be used with SetWindowPos().
277 * This function assumes that 'cmd' is different from the current window
278 * state.
279 */
280UINT Win32BaseWindow::MinMaximize(UINT cmd, LPRECT lpRect)
281{
282 UINT swpFlags = 0;
283 POINT size, iconPos;
284
285 size.x = rectWindow.left;
286 size.y = rectWindow.top;
287
288 if(IsRectEmpty(&windowpos.rcNormalPosition)) {
289 CopyRect(&windowpos.rcNormalPosition, &rectWindow);
290 }
291 if(!HOOK_CallHooksA(WH_CBT, HCBT_MINMAX, getWindowHandle(), cmd))
292 {
293 if(getStyle() & WS_MINIMIZE )
294 {
295 if(!SendMessageA(getWindowHandle(), WM_QUERYOPEN, 0, 0L))
296 return (SWP_NOSIZE | SWP_NOMOVE);
297 }
298 switch( cmd )
299 {
300 case SW_MINIMIZE:
301 if( getStyle() & WS_MAXIMIZE)
302 {
303 setFlags(getFlags() | WIN_RESTORE_MAX);
304 setStyle(getStyle() & ~WS_MAXIMIZE);
305 }
306 else setFlags(getFlags() & ~WIN_RESTORE_MAX);
307
308 setStyle(getStyle() | WS_MINIMIZE);
309
310 if(getParent() == NULL) {
311 SetRect(lpRect, -32000, -32000, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
312 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
313 }
314 else {
315 iconPos.x = windowpos.ptMinPosition.x;
316 iconPos.y = windowpos.ptMinPosition.y;
317 WINPOS_FindIconPos(getWindowHandle(), iconPos);
318 SetRect(lpRect, iconPos.x, iconPos.y, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
319 }
320 break;
321
322 case SW_MAXIMIZE:
323 GetMinMaxInfo(&size, &windowpos.ptMaxPosition, NULL, NULL );
324
325 if(getStyle() & WS_MINIMIZE )
326 {
327 setStyle(getStyle() & ~WS_MINIMIZE);
328 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
329 }
330 setStyle(getStyle() | WS_MAXIMIZE);
331
332 SetRect(lpRect, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y,
333 size.x, size.y );
334 break;
335
336 case SW_RESTORE:
337 if(getStyle() & WS_MINIMIZE)
338 {
339 setStyle(getStyle() & ~WS_MINIMIZE);
340 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(), getStyle(), getExStyle());
341
342 if( getFlags() & WIN_RESTORE_MAX)
343 {
344 /* Restore to maximized position */
345 GetMinMaxInfo(&size, &windowpos.ptMaxPosition, NULL, NULL);
346 setStyle(getStyle() | WS_MAXIMIZE);
347 SetRect(lpRect, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y, size.x, size.y);
348 break;
349 }
350 }
351 else
352 if( !(getStyle() & WS_MAXIMIZE) )
353 return 0;
354 else setStyle(getStyle() & ~WS_MAXIMIZE);
355
356 /* Restore to normal position */
357 *lpRect = windowpos.rcNormalPosition;
358 lpRect->right -= lpRect->left;
359 lpRect->bottom -= lpRect->top;
360 break;
361 }
362 }
363 else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
364
365 return swpFlags;
366}
367//******************************************************************************
368//******************************************************************************
Note: See TracBrowser for help on using the repository browser.