blob: 76f6d87f545f52c468e3b91f514680009c6c4822 [file] [log] [blame]
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001/* MDI.C
2 *
3 * Copyright 1994, Bob Amstadt
4 *
5 * This file contains routines to support MDI features.
6 */
7#include <stdlib.h>
8#include <stdio.h>
Alexandre Julliard490a27e1994-06-08 13:57:50 +00009#include <math.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000010#include "windows.h"
11#include "win.h"
Alexandre Julliard18506551995-01-24 16:21:01 +000012#include "nonclient.h"
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000013#include "mdi.h"
14#include "user.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000015#include "menu.h"
Alexandre Julliard58199531994-04-21 01:20:00 +000016#include "sysmetrics.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000017#include "stddebug.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000018#include "debug.h"
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000019
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000020/**********************************************************************
21 * MDIRecreateMenuList
22 */
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000023void MDIRecreateMenuList(MDICLIENTINFO *ci)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000024{
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000025 HLOCAL hinfo;
26
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000027 char buffer[128];
28 int id, n, index;
29
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000030 dprintf_mdi(stddeb, "MDIRecreateMenuList: hWindowMenu "NPFMT"\n",
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000031 ci->hWindowMenu);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000032
33 id = ci->idFirstChild;
34 while (DeleteMenu(ci->hWindowMenu, id, MF_BYCOMMAND))
35 id++;
36
Alexandre Julliard234bc241994-12-10 13:02:28 +000037 dprintf_mdi(stddeb, "MDIRecreateMenuList: id %04x, idFirstChild %04x\n",
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000038 id, ci->idFirstChild);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000039
40 if (!ci->flagMenuAltered)
41 {
42 ci->flagMenuAltered = TRUE;
43 AppendMenu(ci->hWindowMenu, MF_SEPARATOR, 0, NULL);
44 }
45
46 id = ci->idFirstChild;
47 index = 1;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000048 for (hinfo = ci->infoActiveChildren; hinfo != 0;)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000049 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000050 MDICHILDINFO *chi = USER_HEAP_LIN_ADDR(hinfo);
51
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000052 n = sprintf(buffer, "%d ", index++);
53 GetWindowText(chi->hwnd, buffer + n, sizeof(buffer) - n - 1);
54
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000055 dprintf_mdi(stddeb, "MDIRecreateMenuList: id %04x, '%s'\n",
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000056 id, buffer);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000057
58 AppendMenu(ci->hWindowMenu, MF_STRING, id++, buffer);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000059 hinfo = chi->next;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000060 }
61}
62
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000063/**********************************************************************
64 * MDISetMenu
65 * FIXME: This is not complete.
66 */
67HMENU MDISetMenu(HWND hwnd, BOOL fRefresh, HMENU hmenuFrame, HMENU hmenuWindow)
68{
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000069 dprintf_mdi(stddeb, "WM_MDISETMENU: "NPFMT" %04x "NPFMT" "NPFMT"\n", hwnd, fRefresh, hmenuFrame, hmenuWindow);
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000070 if (!fRefresh) {
71 HWND hwndFrame = GetParent(hwnd);
72 HMENU oldFrameMenu = GetMenu(hwndFrame);
73 SetMenu(hwndFrame, hmenuFrame);
74 return oldFrameMenu;
75 }
76 return 0;
77}
Alexandre Julliard2787be81995-05-22 18:23:01 +000078
79/**********************************************************************
80 * MDIIconArrange
81 */
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000082WORD MDIIconArrange(HWND parent)
Alexandre Julliard2787be81995-05-22 18:23:01 +000083{
84 return ArrangeIconicWindows(parent); /* Any reason why the */
85 /* existing icon arrange */
86 /* can't be used here? */
87 /* -DRP */
88}
89
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000090/**********************************************************************
Alexandre Julliard58199531994-04-21 01:20:00 +000091 * MDICreateChild
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000092 */
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000093HWND MDICreateChild(WND *w, MDICLIENTINFO *ci, HWND parent, LPARAM lParam )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000094{
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000095 MDICREATESTRUCT *cs = (MDICREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000096 HWND hwnd;
Alexandre Julliard2787be81995-05-22 18:23:01 +000097 int spacing;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000098
99 /*
100 * Create child window
101 */
102 cs->style &= (WS_MINIMIZE | WS_MAXIMIZE | WS_HSCROLL | WS_VSCROLL);
Alexandre Julliard2787be81995-05-22 18:23:01 +0000103
104 /* The child windows should probably */
105 /* stagger, shouldn't they? -DRP */
106 spacing = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
107 cs->x = ci->nActiveChildren * spacing;
108 cs->y = ci->nActiveChildren * spacing;
109
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000110 hwnd = CreateWindow( cs->szClass, cs->szTitle,
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000111 WS_CHILD | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS |
112 WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU |
113 WS_THICKFRAME | WS_VISIBLE | cs->style,
114 cs->x, cs->y, cs->cx, cs->cy, parent, (HMENU) 0,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000115 w->hInstance, (SEGPTR)lParam);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000116
117 if (hwnd)
118 {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000119 HANDLE h = USER_HEAP_ALLOC( sizeof(MDICHILDINFO) );
120 MDICHILDINFO *child_info = USER_HEAP_LIN_ADDR(h);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000121
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000122 if (!h)
123 {
124 DestroyWindow(hwnd);
125 return 0;
126 }
127
128 ci->nActiveChildren++;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000129
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000130 child_info->next = ci->infoActiveChildren;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000131 child_info->prev = 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000132 child_info->hwnd = hwnd;
133
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000134 if (ci->infoActiveChildren) {
135 MDICHILDINFO *nextinfo = USER_HEAP_LIN_ADDR(ci->infoActiveChildren);
136 nextinfo->prev = h;
137 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000138
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000139 ci->infoActiveChildren = h;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000140
141 SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
142 }
143
144 return hwnd;
145}
146
147/**********************************************************************
Alexandre Julliard58199531994-04-21 01:20:00 +0000148 * MDIDestroyChild
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000149 */
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000150HWND MDIDestroyChild(WND *w_parent, MDICLIENTINFO *ci, HWND parent,
151 HWND child, BOOL flagDestroy)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000152{
153 MDICHILDINFO *chi;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000154 HLOCAL hinfo;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000155
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000156 hinfo = ci->infoActiveChildren;
157 while (hinfo != 0) {
158 chi = (MDICHILDINFO *)USER_HEAP_LIN_ADDR(hinfo);
159 if (chi->hwnd == child) break;
160 hinfo = chi->next;
161 }
162
163 if (hinfo != 0)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000164 {
165 if (chi->prev)
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000166 ((MDICHILDINFO *)USER_HEAP_LIN_ADDR(chi->prev))->next = chi->next;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000167 if (chi->next)
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000168 ((MDICHILDINFO *)USER_HEAP_LIN_ADDR(chi->next))->prev = chi->prev;
169 if (ci->infoActiveChildren == hinfo)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000170 ci->infoActiveChildren = chi->next;
171
172 ci->nActiveChildren--;
173
174 if (chi->hwnd == ci->hwndActiveChild)
175 SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
176
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000177 USER_HEAP_FREE(hinfo);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000178
179 if (flagDestroy)
180 DestroyWindow(child);
181 }
182
183 return 0;
184}
185
186/**********************************************************************
187 * MDIBringChildToTop
188 */
Alexandre Julliard58199531994-04-21 01:20:00 +0000189void MDIBringChildToTop(HWND parent, WORD id, WORD by_id, BOOL send_to_bottom)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000190{
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000191 HLOCAL hinfo;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000192 MDICHILDINFO *chi;
193 MDICLIENTINFO *ci;
194 WND *w;
195 int i;
196
197 w = WIN_FindWndPtr(parent);
198 ci = (MDICLIENTINFO *) w->wExtra;
199
Alexandre Julliard234bc241994-12-10 13:02:28 +0000200 dprintf_mdi(stddeb, "MDIBringToTop: id %04x, by_id %d\n", id, by_id);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000201
202 if (by_id)
203 id -= ci->idFirstChild;
204 if (!by_id || id < ci->nActiveChildren)
205 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000206 hinfo = ci->infoActiveChildren;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000207
208 if (by_id)
209 {
210 for (i = 0; i < id; i++)
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000211 hinfo = ((MDICHILDINFO *)USER_HEAP_LIN_ADDR(hinfo))->next;
212 chi = USER_HEAP_LIN_ADDR(hinfo);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000213 }
214 else
215 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000216 while (hinfo != 0) {
217 chi = (MDICHILDINFO *)USER_HEAP_LIN_ADDR(hinfo);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000218 if (chi->hwnd == (HWND)id) break;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000219 hinfo = chi->next;
220 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000221 }
222
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000223 if (hinfo == 0)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000224 return;
225
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000226 dprintf_mdi(stddeb, "MDIBringToTop: child "NPFMT"\n", chi->hwnd);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000227 if (hinfo != ci->infoActiveChildren)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000228 {
Alexandre Julliard58199531994-04-21 01:20:00 +0000229 if (ci->flagChildMaximized)
230 {
231 RECT rectOldRestore, rect;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000232
Alexandre Julliard58199531994-04-21 01:20:00 +0000233 w = WIN_FindWndPtr(chi->hwnd);
234
235 rectOldRestore = ci->rectRestore;
236 GetWindowRect(chi->hwnd, &ci->rectRestore);
237
238 rect.top = (ci->rectMaximize.top -
239 (w->rectClient.top - w->rectWindow.top));
240 rect.bottom = (ci->rectMaximize.bottom +
241 (w->rectWindow.bottom - w->rectClient.bottom));
242 rect.left = (ci->rectMaximize.left -
243 (w->rectClient.left - w->rectWindow.left));
244 rect.right = (ci->rectMaximize.right +
245 (w->rectWindow.right - w->rectClient.right));
246 w->dwStyle |= WS_MAXIMIZE;
247 SetWindowPos(chi->hwnd, HWND_TOP, rect.left, rect.top,
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000248 rect.right - rect.left + 1,
Alexandre Julliard58199531994-04-21 01:20:00 +0000249 rect.bottom - rect.top + 1, 0);
250 SendMessage(chi->hwnd, WM_SIZE, SIZE_MAXIMIZED,
251 MAKELONG(w->rectClient.right-w->rectClient.left,
252 w->rectClient.bottom-w->rectClient.top));
253
254 w = WIN_FindWndPtr(ci->hwndActiveChild);
255 w->dwStyle &= ~WS_MAXIMIZE;
256 SetWindowPos(ci->hwndActiveChild, HWND_BOTTOM,
257 rectOldRestore.left, rectOldRestore.top,
258 rectOldRestore.right - rectOldRestore.left + 1,
259 rectOldRestore.bottom - rectOldRestore.top + 1,
260 SWP_NOACTIVATE |
261 (send_to_bottom ? 0 : SWP_NOZORDER));
262 }
263 else
264 {
265 SetWindowPos(chi->hwnd, HWND_TOP, 0, 0, 0, 0,
266 SWP_NOMOVE | SWP_NOSIZE );
267 if (send_to_bottom)
268 {
269 SetWindowPos(ci->hwndActiveChild, HWND_BOTTOM, 0, 0, 0, 0,
270 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
271 }
272 }
273
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000274 if (chi->next)
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000275 ((MDICHILDINFO *)USER_HEAP_LIN_ADDR(chi->next))->prev = chi->prev;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000276
277 if (chi->prev)
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000278 ((MDICHILDINFO *)USER_HEAP_LIN_ADDR(chi->prev))->next = chi->next;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000279
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000280 chi->prev = 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000281 chi->next = ci->infoActiveChildren;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000282 ((MDICHILDINFO *)USER_HEAP_LIN_ADDR(chi->next))->prev = hinfo;
283 ci->infoActiveChildren = hinfo;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000284
285 SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
286 }
287
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000288 dprintf_mdi(stddeb, "MDIBringToTop: pos %04x, hwnd "NPFMT"\n",
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000289 id, chi->hwnd);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000290 }
291}
292
293/**********************************************************************
Alexandre Julliard58199531994-04-21 01:20:00 +0000294 * MDIMaximizeChild
295 */
296LONG MDIMaximizeChild(HWND parent, HWND child, MDICLIENTINFO *ci)
297{
298 WND *w = WIN_FindWndPtr(child);
299 RECT rect;
300
301 MDIBringChildToTop(parent, child, FALSE, FALSE);
302 ci->rectRestore = w->rectWindow;
303
304 rect.top = (ci->rectMaximize.top -
305 (w->rectClient.top - w->rectWindow.top));
306 rect.bottom = (ci->rectMaximize.bottom +
307 (w->rectWindow.bottom - w->rectClient.bottom));
308 rect.left = (ci->rectMaximize.left -
309 (w->rectClient.left - w->rectWindow.left));
310 rect.right = (ci->rectMaximize.right +
311 (w->rectWindow.right - w->rectClient.right));
312 w->dwStyle |= WS_MAXIMIZE;
313 SetWindowPos(child, 0, rect.left, rect.top,
314 rect.right - rect.left + 1, rect.bottom - rect.top + 1,
315 SWP_NOACTIVATE | SWP_NOZORDER);
316
317 ci->flagChildMaximized = TRUE;
318
319 SendMessage(child, WM_SIZE, SIZE_MAXIMIZED,
320 MAKELONG(w->rectClient.right-w->rectClient.left,
321 w->rectClient.bottom-w->rectClient.top));
Alexandre Julliard18506551995-01-24 16:21:01 +0000322 SendMessage(GetParent(parent), WM_NCPAINT, 0, 0);
Alexandre Julliard58199531994-04-21 01:20:00 +0000323
324 return 0;
325}
326
327/**********************************************************************
328 * MDIRestoreChild
329 */
330LONG MDIRestoreChild(HWND parent, MDICLIENTINFO *ci)
331{
332 HWND child;
Alexandre Julliard58199531994-04-21 01:20:00 +0000333
Alexandre Julliardaca05781994-10-17 18:12:41 +0000334 dprintf_mdi(stddeb,"restoring mdi child\n");
Alexandre Julliard988ca971994-06-21 16:15:21 +0000335
Alexandre Julliard58199531994-04-21 01:20:00 +0000336 child = ci->hwndActiveChild;
Alexandre Julliard58199531994-04-21 01:20:00 +0000337 ci->flagChildMaximized = FALSE;
338
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000339 ShowWindow(child, SW_RESTORE); /* display the window */
Alexandre Julliard58199531994-04-21 01:20:00 +0000340 MDIBringChildToTop(parent, child, FALSE, FALSE);
Alexandre Julliard2787be81995-05-22 18:23:01 +0000341 SendMessage(GetParent(parent), WM_NCPAINT, 0, 0);
Alexandre Julliard58199531994-04-21 01:20:00 +0000342
343 return 0;
344}
345
346/**********************************************************************
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000347 * MDIChildActivated
348 */
349LONG MDIChildActivated(WND *w, MDICLIENTINFO *ci, HWND parent)
350{
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000351 HLOCAL hinfo;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000352 MDICHILDINFO *chi;
353 HWND deact_hwnd;
354 HWND act_hwnd;
355 LONG lParam;
356
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000357 dprintf_mdi(stddeb, "MDIChildActivate: top "NPFMT"\n", w->hwndChild);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000358
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000359 hinfo = ci->infoActiveChildren;
360 if (hinfo)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000361 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000362 chi = (MDICHILDINFO *)USER_HEAP_LIN_ADDR(hinfo);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000363 deact_hwnd = ci->hwndActiveChild;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000364 act_hwnd = chi->hwnd; /* FIX: Hack */
365 lParam = ((LONG) deact_hwnd << 16) | (LONG)act_hwnd;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000366
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000367 dprintf_mdi(stddeb, "MDIChildActivate: deact "NPFMT", act "NPFMT"\n",
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000368 deact_hwnd, act_hwnd);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000369
370 ci->hwndActiveChild = act_hwnd;
371
372 if (deact_hwnd != act_hwnd)
373 {
374 MDIRecreateMenuList(ci);
375 SendMessage(deact_hwnd, WM_NCACTIVATE, FALSE, 0);
376 SendMessage(deact_hwnd, WM_MDIACTIVATE, FALSE, lParam);
377 }
378
379 SendMessage(act_hwnd, WM_NCACTIVATE, TRUE, 0);
380 SendMessage(act_hwnd, WM_MDIACTIVATE, TRUE, lParam);
381 }
382
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000383 if (hinfo || ci->nActiveChildren == 0)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000384 {
385 MDIRecreateMenuList(ci);
Alexandre Julliard58199531994-04-21 01:20:00 +0000386 SendMessage(GetParent(parent), WM_NCPAINT, 0, 0);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000387 }
388
389 return 0;
390}
391
392/**********************************************************************
393 * MDICascade
394 */
395LONG MDICascade(HWND parent, MDICLIENTINFO *ci)
396{
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000397 HLOCAL hinfo;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000398 MDICHILDINFO *chi;
399 RECT rect;
400 int spacing, xsize, ysize;
401 int x, y;
402
Alexandre Julliard58199531994-04-21 01:20:00 +0000403 if (ci->flagChildMaximized)
404 MDIRestoreChild(parent, ci);
405
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000406 /* If there aren't any children, don't even bother.
407 */
408 if (ci->nActiveChildren == 0)
409 return 0;
410
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000411 GetClientRect(parent, &rect);
412 spacing = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
Alexandre Julliard58199531994-04-21 01:20:00 +0000413 ysize = rect.bottom - 8 * spacing;
414 xsize = rect.right - 8 * spacing;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000415
Alexandre Julliardaca05781994-10-17 18:12:41 +0000416 dprintf_mdi(stddeb,
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000417 "MDICascade: Client wnd at (%d,%d) - (%d,%d), spacing %d\n",
418 rect.left, rect.top, rect.right, rect.bottom, spacing);
Alexandre Julliardaca05781994-10-17 18:12:41 +0000419 dprintf_mdi(stddeb, "MDICascade: searching for last child\n");
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000420 hinfo = ci->infoActiveChildren;
421 while(1) {
422 chi = USER_HEAP_LIN_ADDR(hinfo);
423 if (chi->next == 0) break;
424 hinfo = chi->next;
425 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000426
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000427 dprintf_mdi(stddeb, "MDICascade: last child is "NPFMT"\n", chi->hwnd);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000428 x = 0;
429 y = 0;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000430 while (hinfo != 0)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000431 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000432 chi = USER_HEAP_LIN_ADDR(hinfo);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000433 dprintf_mdi(stddeb, "MDICascade: move "NPFMT" to (%d,%d) size [%d,%d]\n",
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000434 chi->hwnd, x, y, xsize, ysize);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000435 if (IsIconic(chi->hwnd)) continue;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000436 SetWindowPos(chi->hwnd, 0, x, y, xsize, ysize,
437 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
438
439 x += spacing;
440 y += spacing;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000441
442 hinfo = chi->prev;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000443 }
444
445 return 0;
446}
447
448/**********************************************************************
Alexandre Julliard58199531994-04-21 01:20:00 +0000449 * MDITile
450 */
451LONG MDITile(HWND parent, MDICLIENTINFO *ci)
452{
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000453 HLOCAL hinfo;
Alexandre Julliard58199531994-04-21 01:20:00 +0000454 MDICHILDINFO *chi;
455 RECT rect;
456 int xsize, ysize;
457 int x, y;
458 int rows, columns;
459 int r, c;
460 int i;
461
462 if (ci->flagChildMaximized)
463 MDIRestoreChild(parent, ci);
464
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000465 /* If there aren't any children, don't even bother.
466 */
467 if (ci->nActiveChildren == 0)
468 return 0;
469
Alexandre Julliard58199531994-04-21 01:20:00 +0000470 GetClientRect(parent, &rect);
471 rows = (int) sqrt((double) ci->nActiveChildren);
472 columns = ci->nActiveChildren / rows;
473 ysize = rect.bottom / rows;
474 xsize = rect.right / columns;
475
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000476 hinfo = ci->infoActiveChildren;
Alexandre Julliard58199531994-04-21 01:20:00 +0000477 x = 0;
478 i = 0;
479 for (c = 1; c <= columns; c++)
480 {
481 if (c == columns)
482 {
483 rows = ci->nActiveChildren - i;
484 ysize = rect.bottom / rows;
485 }
486
487 y = 0;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000488 for (r = 1; r <= rows; r++, i++)
Alexandre Julliard58199531994-04-21 01:20:00 +0000489 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000490 chi = (MDICHILDINFO *)USER_HEAP_LIN_ADDR(hinfo);
Alexandre Julliard58199531994-04-21 01:20:00 +0000491 SetWindowPos(chi->hwnd, 0, x, y, xsize, ysize,
492 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
493
494 y += ysize;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000495 hinfo = chi->next;
Alexandre Julliard58199531994-04-21 01:20:00 +0000496 }
497
498 x += xsize;
499 }
500
501
502 return 0;
503}
504
505/**********************************************************************
506 * MDIHandleLButton
507 */
508BOOL MDIHandleLButton(HWND hwndFrame, HWND hwndClient,
509 WORD wParam, LONG lParam)
510{
511 MDICLIENTINFO *ci;
512 WND *w;
513 RECT rect;
514 WORD x;
515
516 w = WIN_FindWndPtr(hwndClient);
517 ci = (MDICLIENTINFO *) w->wExtra;
518
519 if (wParam == HTMENU && ci->flagChildMaximized)
520 {
521 x = LOWORD(lParam);
522
523 NC_GetInsideRect(hwndFrame, &rect);
524 if (x < rect.left + SYSMETRICS_CXSIZE)
525 {
526 SendMessage(ci->hwndActiveChild, WM_SYSCOMMAND,
527 SC_CLOSE, lParam);
528 return TRUE;
529 }
530 else if (x >= rect.right - SYSMETRICS_CXSIZE)
531 {
532 SendMessage(ci->hwndActiveChild, WM_SYSCOMMAND,
533 SC_RESTORE, lParam);
534 return TRUE;
535 }
536 }
537
538 return FALSE;
539}
540
541/**********************************************************************
542 * MDIPaintMaximized
543 */
544LONG MDIPaintMaximized(HWND hwndFrame, HWND hwndClient, WORD message,
545 WORD wParam, LONG lParam)
546{
547 static HBITMAP hbitmapClose = 0;
548 static HBITMAP hbitmapMaximized = 0;
549
550 MDICLIENTINFO *ci;
551 WND *w;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000552 HDC hdc, hdcMem;
553 RECT rect;
Alexandre Julliard58199531994-04-21 01:20:00 +0000554 WND *wndPtr = WIN_FindWndPtr(hwndFrame);
555
556 w = WIN_FindWndPtr(hwndClient);
557 ci = (MDICLIENTINFO *) w->wExtra;
558
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000559 dprintf_mdi(stddeb, "MDIPaintMaximized: frame "NPFMT", client "NPFMT
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000560 ", max flag %d, menu %04x\n", hwndFrame, hwndClient,
Alexandre Julliard58199531994-04-21 01:20:00 +0000561 ci->flagChildMaximized, wndPtr ? wndPtr->wIDmenu : 0);
Alexandre Julliard58199531994-04-21 01:20:00 +0000562
563 if (ci->flagChildMaximized && wndPtr && wndPtr->wIDmenu != 0)
564 {
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000565 NC_DoNCPaint(hwndFrame, wParam, TRUE);
Alexandre Julliard18506551995-01-24 16:21:01 +0000566
Alexandre Julliard58199531994-04-21 01:20:00 +0000567 hdc = GetDCEx(hwndFrame, 0, DCX_CACHE | DCX_WINDOW);
Alexandre Julliard18506551995-01-24 16:21:01 +0000568 if (!hdc) return 0;
Alexandre Julliard58199531994-04-21 01:20:00 +0000569
570 hdcMem = CreateCompatibleDC(hdc);
571
572 if (hbitmapClose == 0)
573 {
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000574 hbitmapClose = LoadBitmap(0, MAKEINTRESOURCE(OBM_OLD_CLOSE));
Alexandre Julliard58199531994-04-21 01:20:00 +0000575 hbitmapMaximized = LoadBitmap(0, MAKEINTRESOURCE(OBM_RESTORE));
576 }
577
Alexandre Julliardaca05781994-10-17 18:12:41 +0000578 dprintf_mdi(stddeb,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000579 "MDIPaintMaximized: hdcMem "NPFMT", close bitmap "NPFMT", "
580 "maximized bitmap "NPFMT"\n",
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000581 hdcMem, hbitmapClose, hbitmapMaximized);
Alexandre Julliard58199531994-04-21 01:20:00 +0000582
583 NC_GetInsideRect(hwndFrame, &rect);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000584 rect.top += (wndPtr->dwStyle & WS_CAPTION) ? SYSMETRICS_CYSIZE + 1 : 0;
Alexandre Julliard58199531994-04-21 01:20:00 +0000585 SelectObject(hdcMem, hbitmapClose);
586 BitBlt(hdc, rect.left, rect.top + 1,
587 SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
588 hdcMem, 1, 1, SRCCOPY);
589
590 NC_GetInsideRect(hwndFrame, &rect);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000591 rect.top += (wndPtr->dwStyle & WS_CAPTION) ? SYSMETRICS_CYSIZE + 1 : 0;
Alexandre Julliard58199531994-04-21 01:20:00 +0000592 rect.left = rect.right - SYSMETRICS_CXSIZE;
593 SelectObject(hdcMem, hbitmapMaximized);
594 BitBlt(hdc, rect.left, rect.top + 1,
595 SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
596 hdcMem, 1, 1, SRCCOPY);
597
598 NC_GetInsideRect(hwndFrame, &rect);
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000599 rect.top += (wndPtr->dwStyle & WS_CAPTION) ? SYSMETRICS_CYSIZE + 1 : 0;
600 rect.left += SYSMETRICS_CXSIZE;
Alexandre Julliard58199531994-04-21 01:20:00 +0000601 rect.right -= SYSMETRICS_CXSIZE;
602 rect.bottom = rect.top + SYSMETRICS_CYMENU;
603
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000604 MENU_DrawMenuBar(hdc, &rect, hwndFrame, FALSE);
Alexandre Julliard58199531994-04-21 01:20:00 +0000605
606 DeleteDC(hdcMem);
607 ReleaseDC(hwndFrame, hdc);
608 }
609 else
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000610 return DefWindowProc(hwndFrame, message, wParam, lParam);
Alexandre Julliard58199531994-04-21 01:20:00 +0000611
Alexandre Julliard18506551995-01-24 16:21:01 +0000612 return 0;
Alexandre Julliard58199531994-04-21 01:20:00 +0000613}
614
615/**********************************************************************
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000616 * MDIClientWndProc
617 *
618 * This function is the handler for all MDI requests.
619 */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000620LRESULT MDIClientWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000621{
622 LPCREATESTRUCT cs;
623 LPCLIENTCREATESTRUCT ccs;
624 MDICLIENTINFO *ci;
625 WND *w;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000626
627 w = WIN_FindWndPtr(hwnd);
628 ci = (MDICLIENTINFO *) w->wExtra;
629
630 switch (message)
631 {
632 case WM_CHILDACTIVATE:
633 return MDIChildActivated(w, ci, hwnd);
634
635 case WM_CREATE:
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000636 cs = (LPCREATESTRUCT) PTR_SEG_TO_LIN(lParam);
637 ccs = (LPCLIENTCREATESTRUCT) PTR_SEG_TO_LIN(cs->lpCreateParams);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000638 ci->hWindowMenu = ccs->hWindowMenu;
639 ci->idFirstChild = ccs->idFirstChild;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000640 ci->infoActiveChildren = 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000641 ci->flagMenuAltered = FALSE;
642 ci->flagChildMaximized = FALSE;
643 w->dwStyle |= WS_CLIPCHILDREN;
644
Alexandre Julliard58199531994-04-21 01:20:00 +0000645 GetClientRect(w->hwndParent, &ci->rectMaximize);
646 MoveWindow(hwnd, 0, 0,
647 ci->rectMaximize.right, ci->rectMaximize.bottom, 1);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000648
649 return 0;
650
651 case WM_MDIACTIVATE:
Alexandre Julliard58199531994-04-21 01:20:00 +0000652 MDIBringChildToTop(hwnd, wParam, FALSE, FALSE);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000653 return 0;
654
655 case WM_MDICASCADE:
656 return MDICascade(hwnd, ci);
657
658 case WM_MDICREATE:
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000659 return (LONG)MDICreateChild(w, ci, hwnd, lParam );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000660
661 case WM_MDIDESTROY:
Alexandre Julliard58199531994-04-21 01:20:00 +0000662 return MDIDestroyChild(w, ci, hwnd, wParam, TRUE);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000663
664 case WM_MDIGETACTIVE:
665 return ((LONG) ci->hwndActiveChild |
666 ((LONG) ci->flagChildMaximized << 16));
667
668 case WM_MDIICONARRANGE:
Alexandre Julliard2787be81995-05-22 18:23:01 +0000669 return MDIIconArrange(hwnd);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000670
671 case WM_MDIMAXIMIZE:
Alexandre Julliard58199531994-04-21 01:20:00 +0000672 return MDIMaximizeChild(hwnd, wParam, ci);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000673
Alexandre Julliard58199531994-04-21 01:20:00 +0000674 case WM_MDINEXT:
675 MDIBringChildToTop(hwnd, wParam, FALSE, TRUE);
676 break;
677
678 case WM_MDIRESTORE:
679 return MDIRestoreChild(hwnd, ci);
680
681 case WM_MDISETMENU:
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000682 return MDISetMenu(hwnd, wParam, LOWORD(lParam), HIWORD(lParam));
Alexandre Julliard58199531994-04-21 01:20:00 +0000683
684 case WM_MDITILE:
685 return MDITile(hwnd, ci);
686
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000687 case WM_NCACTIVATE:
688 SendMessage(ci->hwndActiveChild, message, wParam, lParam);
689 break;
690
691 case WM_PARENTNOTIFY:
692 if (wParam == WM_DESTROY)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000693#ifdef WINELIB32
694 return MDIDestroyChild(w, ci, hwnd, lParam, FALSE);
695#else
Alexandre Julliard58199531994-04-21 01:20:00 +0000696 return MDIDestroyChild(w, ci, hwnd, LOWORD(lParam), FALSE);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000697#endif
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000698 else if (wParam == WM_LBUTTONDOWN)
Alexandre Julliard58199531994-04-21 01:20:00 +0000699 MDIBringChildToTop(hwnd, ci->hwndHitTest, FALSE, FALSE);
700 break;
701
702 case WM_SIZE:
703 GetClientRect(w->hwndParent, &ci->rectMaximize);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000704 break;
705
706 }
707
708 return DefWindowProc(hwnd, message, wParam, lParam);
709}
710
711/**********************************************************************
712 * DefFrameProc (USER.445)
713 *
714 */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000715LRESULT DefFrameProc(HWND hwnd, HWND hwndMDIClient, UINT message,
716 WPARAM wParam, LPARAM lParam)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000717{
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +0000718 if (hwndMDIClient)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000719 {
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +0000720 switch (message)
721 {
722 case WM_COMMAND:
723 MDIBringChildToTop(hwndMDIClient, wParam, TRUE, FALSE);
724 break;
Alexandre Julliard58199531994-04-21 01:20:00 +0000725
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +0000726 case WM_NCLBUTTONDOWN:
727 if (MDIHandleLButton(hwnd, hwndMDIClient, wParam, lParam))
728 return 0;
729 break;
730
731 case WM_NCACTIVATE:
732 SendMessage(hwndMDIClient, message, wParam, lParam);
733 return MDIPaintMaximized(hwnd, hwndMDIClient,
734 message, wParam, lParam);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000735
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +0000736 case WM_NCPAINT:
737 return MDIPaintMaximized(hwnd, hwndMDIClient,
738 message, wParam, lParam);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000739
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +0000740 case WM_SETFOCUS:
741 SendMessage(hwndMDIClient, WM_SETFOCUS, wParam, lParam);
742 break;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000743
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +0000744 case WM_SIZE:
745 MoveWindow(hwndMDIClient, 0, 0,
746 LOWORD(lParam), HIWORD(lParam), TRUE);
747 break;
748 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000749 }
750
751 return DefWindowProc(hwnd, message, wParam, lParam);
752}
753
754/**********************************************************************
755 * DefMDIChildProc (USER.447)
756 *
757 */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000758#ifdef WINELIB32
759LONG DefMDIChildProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
760#else
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000761LONG DefMDIChildProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000762#endif
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000763{
764 MDICLIENTINFO *ci;
765 WND *w;
766
767 w = WIN_FindWndPtr(GetParent(hwnd));
768 ci = (MDICLIENTINFO *) w->wExtra;
769
770 switch (message)
771 {
772 case WM_NCHITTEST:
773 ci->hwndHitTest = hwnd;
774 break;
775
776 case WM_NCPAINT:
Alexandre Julliard18506551995-01-24 16:21:01 +0000777 NC_DoNCPaint( hwnd, hwnd == ci->hwndActiveChild, FALSE );
778 return 0;
Alexandre Julliard58199531994-04-21 01:20:00 +0000779
780 case WM_SYSCOMMAND:
781 switch (wParam)
782 {
783 case SC_MAXIMIZE:
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000784 return SendMessage(GetParent(hwnd), WM_MDIMAXIMIZE, (WPARAM)hwnd, 0);
Alexandre Julliard58199531994-04-21 01:20:00 +0000785
786 case SC_RESTORE:
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000787 return SendMessage(GetParent(hwnd), WM_MDIRESTORE, (WPARAM)hwnd, 0);
Alexandre Julliard58199531994-04-21 01:20:00 +0000788 }
789 break;
790
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000791 }
792
793 return DefWindowProc(hwnd, message, wParam, lParam);
794}
795
796/**********************************************************************
797 * TranslateMDISysAccel (USER.451)
798 *
799 */
800BOOL TranslateMDISysAccel(HWND hwndClient, LPMSG msg)
801{
802 return 0;
803}
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000804
805
806/***********************************************************************
807 * CalcChildScroll (USER.462)
808 */
809void CalcChildScroll( HWND hwnd, WORD scroll )
810{
811 RECT childRect, clientRect;
812 HWND hwndChild;
813
814 GetClientRect( hwnd, &clientRect );
815 SetRectEmpty( &childRect );
816 hwndChild = GetWindow( hwnd, GW_CHILD );
817 while (hwndChild)
818 {
819 WND *wndPtr = WIN_FindWndPtr( hwndChild );
820 UnionRect( &childRect, &wndPtr->rectWindow, &childRect );
821 hwndChild = wndPtr->hwndNext;
822 }
823 UnionRect( &childRect, &clientRect, &childRect );
824
825 if ((scroll == SB_HORZ) || (scroll == SB_BOTH))
826 {
827 SetScrollRange( hwnd, SB_HORZ, childRect.left,
828 childRect.right - clientRect.right, FALSE );
829 SetScrollPos( hwnd, SB_HORZ, clientRect.left - childRect.left, TRUE );
830 }
831 if ((scroll == SB_VERT) || (scroll == SB_BOTH))
832 {
833 SetScrollRange( hwnd, SB_VERT, childRect.top,
834 childRect.bottom - clientRect.bottom, FALSE );
835 SetScrollPos( hwnd, SB_HORZ, clientRect.top - childRect.top, TRUE );
836 }
837}