|
|
1.1 root 1: /***************************************************************************
2: * *
3: * MODULE : infoctrl.c *
4: * *
5: * PURPOSE : Functions for the infoctrl control class *
6: * *
7: ***************************************************************************/
8: /*
9: * INFOCTRL.C
10: *
11: * This module implements a custom information display control which
12: * can present up to 7 seperate strings of information at once and is
13: * sizeable and moveable with the mouse.
14: */
15:
16: #include <windows.h>
17: #include <string.h>
18: #include <memory.h>
19: #include "infoctrl.h"
20: #include "track.h"
21:
22: CHAR szClass[] = "InfoCtrl_class";
23: DWORD cCreated = 0;
24: CHAR szNULL[] = "";
25: INT cxMargin = 0;
26: INT cyMargin = 0;
27: HBRUSH hFocusBrush;
28:
29:
1.1.1.2 ! root 30: LONG APIENTRY InfoCtrlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
1.1 root 31: VOID MyDrawText(HDC hdc, LPRECT lprc, PSTR psz, DWORD wFormat);
32: VOID DrawFocus(HDC hdc, HWND hwnd, DWORD style);
33: INT CountWindows(HWND hwndParent);
34: VOID GetCascadeWindowPos(HWND hwndParent, INT iWindow, LPRECT lprc);
35:
36:
37: /****************************************************************************
38: * *
39: * FUNCTION : *
40: * *
41: * PURPOSE : *
42: * *
43: * RETURNS : *
44: * *
45: ****************************************************************************/
46: HWND CreateInfoCtrl(
47: LPSTR pszCenter, // NULL is ok.
48: INT x,
49: INT y,
50: INT cx,
51: INT cy,
52: HWND hwndParent,
53: HANDLE hInst,
54: LPSTR pszUL, // NULLs here are fine.
55: LPSTR pszUC,
56: LPSTR pszUR,
57: LPSTR pszLL,
58: LPSTR pszLC,
59: LPSTR pszLR,
60: DWORD style,
61: HMENU id,
62: DWORD dwUser)
63: {
64: INFOCTRL_DATA *picd;
65: HWND hwnd;
66:
67: if (!cCreated) {
68: WNDCLASS wc;
69: TEXTMETRIC metrics;
70: HDC hdc;
71:
72: wc.style = CS_VREDRAW | CS_HREDRAW;
1.1.1.2 ! root 73: wc.lpfnWndProc = InfoCtrlWndProc;
1.1 root 74: wc.cbClsExtra = 0;
75: wc.cbWndExtra = ICCBWNDEXTRA;
76: wc.hInstance = hInst;
77: wc.hIcon = NULL;
78: wc.hCursor = NULL;
79: wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
80: wc.lpszMenuName = NULL;
81: wc.lpszClassName = szClass;
82:
83: RegisterClass(&wc);
84:
85: hdc = GetDC(hwndParent);
86: GetTextMetrics(hdc, &metrics);
87: cyMargin = metrics.tmHeight;
88: cxMargin = metrics.tmAveCharWidth * 2;
89: ReleaseDC(hwndParent, hdc);
90: hFocusBrush = CreateSolidBrush(RGB(0, 0, 255));
91: }
92:
93: if (!(picd = (INFOCTRL_DATA *)LocalAlloc(LPTR, sizeof(INFOCTRL_DATA))))
94: return(FALSE);
95:
96: if (pszCenter) {
1.1.1.2 ! root 97: picd->pszCenter = (PSTR)(PSTR)LocalAlloc(LPTR, strlen(pszCenter) + 1);
! 98: strcpy(picd->pszCenter, pszCenter);
1.1 root 99: } else {
100: picd->pszCenter = NULL;
101: }
102:
103: if (pszUL) {
1.1.1.2 ! root 104: picd->pszUL = (PSTR)(PSTR)LocalAlloc(LPTR, strlen(pszUL) + 1);
! 105: strcpy(picd->pszUL, pszUL);
1.1 root 106: } else {
107: picd->pszUL = NULL;
108: }
109: if (pszUC) {
1.1.1.2 ! root 110: picd->pszUC = (PSTR)LocalAlloc(LPTR, strlen(pszUC) + 1);
! 111: strcpy(picd->pszUC, pszUC);
1.1 root 112: } else {
113: picd->pszUC = NULL;
114: }
115: if (pszUR) {
1.1.1.2 ! root 116: picd->pszUR = (PSTR)LocalAlloc(LPTR, strlen(pszUR) + 1);
! 117: strcpy(picd->pszUR, pszUR);
1.1 root 118: } else {
119: picd->pszUR = NULL;
120: }
121: if (pszLL) {
1.1.1.2 ! root 122: picd->pszLL = (PSTR)LocalAlloc(LPTR, strlen(pszLL) + 1);
! 123: strcpy(picd->pszLL, pszLL);
1.1 root 124: } else {
125: picd->pszLL = NULL;
126: }
127: if (pszLC) {
1.1.1.2 ! root 128: picd->pszLC = (PSTR)LocalAlloc(LPTR, strlen(pszLC) + 1);
! 129: strcpy(picd->pszLC, pszLC);
1.1 root 130: } else {
131: picd->pszLC = NULL;
132: }
133: if (pszLR) {
1.1.1.2 ! root 134: picd->pszLR = (PSTR)LocalAlloc(LPTR, strlen(pszLR) + 1);
! 135: strcpy(picd->pszLR, pszLR);
1.1 root 136: } else {
137: picd->pszLR = NULL;
138: }
139:
140: picd->style = style;
141: picd->hInst = hInst;
142:
143: if (hwnd = CreateWindow(szClass, szNULL,
144: WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
145: x, y, cx, cy, hwndParent, id, hInst, (LPSTR)picd)) {
146: cCreated++;
147: SetWindowLong(hwnd, GWL_USER, dwUser);
148: BringWindowToTop(hwnd);
149: ShowWindow(hwnd, SW_SHOW);
150: return(hwnd);
151: }
152: return(FALSE);
153: }
154:
155:
156:
157:
158: /****************************************************************************
159: * *
160: * FUNCTION : MyDrawText *
161: * *
162: * PURPOSE : Draws psz within lprc in hdc according to wFormat. *
163: * *
164: * RETURNS : Nothing. *
165: * *
166: ****************************************************************************/
167: VOID MyDrawText(
168: HDC hdc,
169: LPRECT lprc,
170: PSTR psz,
171: DWORD wFormat)
172: {
173: RECT rc;
174: DWORD cx;
175:
176: if (psz == NULL || !*psz)
177: return; // notin to draw dude.
178:
179: SetRect(&rc, 0, 0, 1, 0);
180: DrawText(hdc, psz, -1, &rc, DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE);
181: cx = min(rc.right - rc.left, lprc->right - lprc->left);
182: CopyRect(&rc, lprc);
183: switch (wFormat & (DT_LEFT | DT_CENTER | DT_RIGHT)) {
184: case DT_LEFT:
185: rc.right = rc.left + cx;
186: break;
187:
188: case DT_CENTER:
189: cx = (rc.right - rc.left - cx) / 2;
190: rc.right -= cx;
191: rc.left += cx;
192: break;
193:
194: case DT_RIGHT:
195: rc.left = rc.right - cx;
196: break;
197: }
198: DrawText(hdc, psz, -1, &rc, wFormat | DT_VCENTER);
199: }
200:
201:
202:
203:
204: /****************************************************************************
205: * *
206: * FUNCTION : InfoCtrlWndProc *
207: * *
208: * PURPOSE : Main window proc for info controls *
209: * *
210: * RETURNS : case dependent *
211: * *
212: ****************************************************************************/
213: LONG APIENTRY InfoCtrlWndProc(
214: HWND hwnd,
1.1.1.2 ! root 215: UINT msg,
1.1 root 216: WPARAM wParam,
217: LPARAM lParam)
218: {
219: INFOCTRL_DATA *picd;
220: INT i;
221: RECT rc;
222: HDC hdc;
223:
224: switch (msg) {
225: case WM_CREATE:
226: /*
227: * Info controls keep their information in the GWL_INFODATA window
228: * word.
229: */
230: SetWindowLong(hwnd, GWL_INFODATA,
231: (DWORD)(DWORD)(((LPCREATESTRUCT)lParam)->lpCreateParams));
232: break;
233:
234: case WM_SIZE:
235: /*
236: * size the info control, updating the hittest rectangles.
237: * The window is only allowed to get so small.
238: */
239: if ((short)LOWORD(lParam) < 2 * cxMargin || (short)HIWORD(lParam) < 2 * cyMargin) {
240: MoveWindow(hwnd, 0, 0, max((short)LOWORD(lParam), 2 * cxMargin),
241: max((short)HIWORD(lParam), 2 * cyMargin), TRUE);
242: } else {
243: picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
244: SetRect(&picd->rcFocusUL, 0, 0, cxMargin, cyMargin);
245: SetRect(&picd->rcFocusUR, (short)LOWORD(lParam) - cxMargin, 0,
246: (short)LOWORD(lParam), cyMargin);
247: SetRect(&picd->rcFocusLL, 0, (short)HIWORD(lParam) - cyMargin,
248: cxMargin, (INT)HIWORD(lParam));
249: SetRect(&picd->rcFocusLR, picd->rcFocusUR.left, picd->rcFocusLL.top,
250: picd->rcFocusUR.right, picd->rcFocusLL.bottom);
251: }
252: break;
253:
254:
255: case WM_DESTROY:
256: /*
257: * Info control death:
258: *
259: * Inform out parent - last chance to access GWL_USER.
260: * Free our information if it still exists.
261: * Free all strings associated with this control.
262: */
263: {
264: PSTR *ppsz;
265:
266: SendMessage(GetParent(hwnd), ICN_BYEBYE, (WPARAM)hwnd,
267: GetWindowLong(hwnd, GWL_USER));
268: SetWindowLong(hwnd, GWL_USER, 0);
269:
270: picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
271: if (picd) {
272: ppsz = &picd->pszUL;
273: for (i = 0; i < 5; i++, ppsz++) {
274: if (*ppsz) {
275: LocalUnlock((HANDLE)*ppsz);
276: *ppsz = (PSTR)LocalFree((HANDLE)*ppsz);
277: }
278: }
279: LocalUnlock((HANDLE)picd);
280: LocalFree((HANDLE)picd);
281: SetWindowLong(hwnd, GWL_INFODATA, 0);
282: }
283: }
284: break;
285:
286: case WM_SETFOCUS:
287: case WM_KILLFOCUS:
288: /*
289: * When focus changes:
290: *
291: * Alter our look apropriately
292: * Bring ourselves to the top if necessary.
293: * Inform our parent.
294: * Repaint the focus portion of ourselves.
295: * Call DefWindowProc()
296: */
297: picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
298: if (picd != NULL) {
299: if (picd->style & ICSTY_SHOWFOCUS) {
300: if (msg == WM_SETFOCUS)
301: picd->style |= ICSTY_HASFOCUS;
302: else
303: picd->style &= ~ICSTY_HASFOCUS;
304: BringWindowToTop(hwnd);
305: // notify parent
306: SendMessage(GetParent(hwnd), ICN_HASFOCUS,
307: msg == WM_SETFOCUS, (LPARAM)hwnd);
308: } else {
309: picd->style &= ~ICSTY_HASFOCUS;
310: }
311: hdc = GetDC(hwnd);
312: DrawFocus(hdc, hwnd, picd->style);
313: ReleaseDC(hwnd, hdc);
314: }
315: goto DoDWP;
316: break;
317:
318: case WM_MOUSEMOVE:
319: /*
320: * Keep the cursor updated to show sizing or moving state.
321: */
322: {
323: LPSTR cursor;
324:
325: picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
326: if (picd->style & ICSTY_SHOWFOCUS) {
327:
328: if ((INT)HIWORD(lParam) < cyMargin) {
329: if ((short)LOWORD(lParam) < cxMargin) {
330: cursor = IDC_SIZENWSE;
331: } else if ((short)LOWORD(lParam) > picd->rcFocusUR.left) {
332: cursor = IDC_SIZENESW;
333: } else {
334: cursor = IDC_SIZENS;
335: }
336: } else if ((INT)HIWORD(lParam) > picd->rcFocusLL.top) {
337: if ((short)LOWORD(lParam) < cxMargin) {
338: cursor = IDC_SIZENESW;
339: } else if ((short)LOWORD(lParam) > picd->rcFocusUR.left) {
340: cursor = IDC_SIZENWSE;
341: } else {
342: cursor = IDC_SIZENS;
343: }
344: } else {
345: if ((short)LOWORD(lParam) < cxMargin) {
346: cursor = IDC_SIZEWE;
347: } else if ((short)LOWORD(lParam) > picd->rcFocusUR.left) {
348: cursor = IDC_SIZEWE;
349: } else {
350: cursor = IDC_CROSS;
351: }
352: }
353: } else {
354: cursor = IDC_ARROW;
355: }
356: SetCursor(LoadCursor(NULL, cursor));
357: }
358: break;
359:
360: case WM_LBUTTONDOWN:
361: /*
362: * Track window according do mouse location.
363: */
364: picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
365: if (picd->style & ICSTY_SHOWFOCUS) {
366: DWORD fs = 0;
367:
368: if (!(picd->style & ICSTY_HASFOCUS)) {
369: SetFocus(hwnd);
370: }
371:
372: if ((short)HIWORD(lParam) < cyMargin) {
373: fs = TF_TOP;
374: } else if ((INT)HIWORD(lParam) > picd->rcFocusLL.top) {
375: fs = TF_BOTTOM;
376: }
377: if ((short)LOWORD(lParam) < cxMargin) {
378: fs |= TF_LEFT;
379: } else if ((short)LOWORD(lParam) > picd->rcFocusUR.left) {
380: fs |= TF_RIGHT;
381: } else if (fs == 0) {
382: fs = TF_MOVE;
383: }
384:
385: GetClientRect(hwnd, &rc);
386: ClientToScreen(hwnd, (LPPOINT)&rc.left);
387: ClientToScreen(hwnd, (LPPOINT)&rc.right);
388: ScreenToClient(GetParent(hwnd), (LPPOINT)&rc.left);
389: ScreenToClient(GetParent(hwnd), (LPPOINT)&rc.right);
390: if (TrackRect(picd->hInst, GetParent(hwnd),
391: rc.left, rc.top, rc.right, rc.bottom,
392: 2 * cxMargin, 2 * cyMargin,
393: fs | TF_ALLINBOUNDARY, &rc)) {
394:
395: MoveWindow(hwnd, rc.left, rc.top, rc.right - rc.left,
396: rc.bottom - rc.top, TRUE);
397: }
398: }
399: break;
400:
401: case ICM_SETSTRING:
402: /*
403: * This message is sent when a info control string value is changeing.
404: *
405: * wParam = ICSID_ constant
406: * lParam = new string.
407: *
408: * If new string is different from old, free old and allocate space
409: * for new one and copy in.
410: * Redraw invalidated part of info control.
411: */
412: {
413: PSTR *ppsz;
414:
415: picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
416: ppsz = (PSTR *)&picd->pszUL + wParam;
417:
418: if (lParam == NULL)
419: lParam = (DWORD)(LPSTR)szNULL;
420:
421: if (*ppsz) {
1.1.1.2 ! root 422: if (!strcmp(*ppsz, (LPSTR)lParam)) {
1.1 root 423: return 0;
424: }
425: LocalUnlock((HANDLE)*ppsz);
426: *ppsz = (PSTR)LocalFree((HANDLE)*ppsz);
427: }
428: if (lParam) {
1.1.1.2 ! root 429: *ppsz = (PSTR)LocalAlloc(LPTR, strlen((LPSTR)lParam) + 1);
! 430: strcpy((LPSTR)*ppsz, (LPSTR)lParam);
1.1 root 431: }
432: GetClientRect(hwnd, &rc);
433: switch (wParam) {
434: case ICSID_UL:
435: case ICSID_UC:
436: case ICSID_UR:
437: rc.bottom = cyMargin;
438: break;
439:
440: case ICSID_LL:
441: case ICSID_LC:
442: case ICSID_LR:
443: rc.top = rc.bottom - cyMargin;
444: break;
445:
446: case ICSID_CENTER:
447: InflateRect(&rc, -cxMargin, -cyMargin);
448: break;
449: }
450: InvalidateRect(hwnd, &rc, TRUE);
451: UpdateWindow(hwnd);
452: }
453: break;
454:
455: case WM_PAINT:
456: /*
457: * Paint ourselves.
458: *
459: * Draw frame.
460: * Draw info strings.
461: * Send ownerdraw message to parent if ICSTY_OWNERDRAW.
462: */
463: {
464: PAINTSTRUCT ps;
465: HANDLE brush;
466:
467: picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
468: BeginPaint(hwnd, &ps);
469: // erasure should have already been done for us.
470: GetClientRect(hwnd, &rc);
471: brush = GetStockObject(BLACK_BRUSH);
472: InflateRect(&rc, -cxMargin / 2, -cyMargin / 2);
473: FrameRect(ps.hdc, &rc, brush);
474: InflateRect(&rc, cxMargin / 2, cyMargin / 2);
475: SetRect(&rc, picd->rcFocusUL.right, 0, picd->rcFocusUR.left,
476: cyMargin);
477: MyDrawText(ps.hdc, &rc, picd->pszUR, DT_RIGHT);
478: MyDrawText(ps.hdc, &rc, picd->pszUL, DT_LEFT);
479: MyDrawText(ps.hdc, &rc, picd->pszUC, DT_CENTER);
480: SetRect(&rc, picd->rcFocusLL.right, picd->rcFocusLL.top,
481: picd->rcFocusLR.left, picd->rcFocusLR.bottom);
482: MyDrawText(ps.hdc, &rc, picd->pszLR, DT_RIGHT);
483: MyDrawText(ps.hdc, &rc, picd->pszLL, DT_LEFT);
484: MyDrawText(ps.hdc, &rc, picd->pszLC, DT_CENTER);
485:
486: GetClientRect(hwnd, &rc);
487: InflateRect(&rc, -cxMargin, -cyMargin);
488: if (picd->style & ICSTY_OWNERDRAW) {
489: OWNERDRAWPS odps;
490:
491: if (IntersectRect(&odps.rcPaint, &rc, &ps.rcPaint)) {
492: if (IntersectClipRect(ps.hdc, rc.left, rc.top, rc.right,
493: rc.bottom) != NULLREGION) {
494: odps.rcBound = rc;
495: odps.hdc = ps.hdc;
496: odps.dwUser = GetWindowLong(hwnd, GWL_USER);
497: SendMessage(GetParent(hwnd), ICN_OWNERDRAW,
498: GetWindowLong(hwnd, GWL_ID), (DWORD)(LPSTR)&odps);
499: }
500: }
501: } else {
502: MyDrawText(ps.hdc, &rc, picd->pszCenter, DT_LEFT | DT_WORDBREAK | DT_EXPANDTABS);
503: }
504: DrawFocus(ps.hdc, hwnd, picd->style);
505: EndPaint(hwnd, &ps);
506: }
507: break;
508:
509: DoDWP:
510: default:
511: return (DefWindowProc(hwnd, msg, wParam, lParam));
512: }
513: return (NULL);
514: }
515:
516:
517: /****************************************************************************
518: * *
519: * FUNCTION : DrawFocus *
520: * *
521: * PURPOSE : To draw focus part of info control. *
522: * *
523: * RETURNS : nothing *
524: * *
525: ****************************************************************************/
526: VOID DrawFocus(
527: HDC hdc,
528: HWND hwnd,
529: DWORD style)
530: {
531: RECT rc;
532:
533: GetClientRect(hwnd, &rc);
534: FrameRect(hdc, &rc, style & ICSTY_HASFOCUS ?
535: hFocusBrush : GetStockObject(GRAY_BRUSH));
536: }
537:
538:
539:
540:
541: /****************************************************************************
542: * *
543: * FUNCTION : CountWindows *
544: * *
545: * PURPOSE : Counts how many info controls the parent of this window has*
546: * *
547: * RETURNS : the count. *
548: * *
549: ****************************************************************************/
550: INT CountWindows(
551: register HWND hwndParent)
552: {
553: INT cWindows = 0;
554: register HWND hwnd;
555:
556: for (hwnd=GetWindow(hwndParent, GW_CHILD);
557: hwnd;
558: hwnd= GetWindow(hwnd, GW_HWNDNEXT)) {
559: cWindows++;
560: }
561: return(cWindows);
562: }
563:
564:
565:
566: /****************************************************************************
567: * *
568: * FUNCTION : GetCascadeWindowPos *
569: * *
570: * PURPOSE : Based on a window index and the parent window size, *
571: * calculates where to place a cascaded window. *
572: * *
573: * RETURNS : rectangle in lprc. *
574: * *
575: ****************************************************************************/
576: VOID GetCascadeWindowPos(
577: HWND hwndParent,
578: INT iWindow,
579: LPRECT lprc)
580: {
581: RECT rc;
582: INT cStack;
583: register INT dxClient, dyClient;
584:
585: /* Compute the width and breadth of the situation. */
586: GetClientRect(hwndParent, (LPRECT)&rc);
587: dxClient = rc.right - rc.left;
588: dyClient = rc.bottom - rc.top;
589:
590: /* How many windows per stack? */
591: cStack = dyClient / (3 * cyMargin);
592:
593: lprc->right = dxClient - (cStack * cxMargin);
594: lprc->bottom = dyClient - (cStack * cyMargin);
595:
596: cStack++; /* HACK!: Mod by cStack+1 */
597:
598: lprc->left = (iWindow % cStack) * cxMargin;
599: lprc->top = (iWindow % cStack) * cyMargin;
600: }
601:
602:
603:
604:
605: /****************************************************************************
606: * *
607: * FUNCTION : MyCascadeChildWindows *
608: * *
609: * PURPOSE : Cascades all children of a parent window *
610: * *
611: * RETURNS : nothing *
612: * *
613: ****************************************************************************/
614: VOID MyCascadeChildWindows(
615: register HWND hwndParent)
616: {
617: INT i;
618: INT cWindows;
619: RECT rc;
620: DWORD wFlags;
621: register HWND hwndMove;
622: HANDLE hDefer;
623:
624: cWindows = CountWindows(hwndParent);
625:
626: if (!cWindows)
627: return;
628:
629: hwndMove = GetWindow(hwndParent, GW_CHILD);
630:
631: hDefer = BeginDeferWindowPos(cWindows);
632:
633: for (i=0; i < cWindows; i++) {
634: GetCascadeWindowPos(hwndParent, i, (LPRECT)&rc);
635:
636: wFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS;
637:
638: /* Size the window. */
639: hDefer = DeferWindowPos(hDefer,
640: hwndMove, NULL,
641: rc.left, rc.top,
642: rc.right, rc.bottom,
643: wFlags);
644:
645: hwndMove = GetWindow(hwndMove, GW_HWNDNEXT);
646: }
647:
648: EndDeferWindowPos(hDefer);
649: }
650:
651:
652: /****************************************************************************
653: * *
654: * FUNCTION : TileChildWindows *
655: * *
656: * PURPOSE : Tiles all children of a parent window *
657: * *
658: * RETURNS : nothing. *
659: * *
660: ****************************************************************************/
661: VOID TileChildWindows(
662: register HWND hwndParent)
663: {
664: INT i;
665: INT dx;
666: INT dy;
667: INT xRes;
668: INT yRes;
669: INT iCol;
670: INT iRow;
671: INT cCols;
672: INT cRows;
673: INT cExtra;
674: INT cWindows;
675: register HWND hwndMove;
676: RECT rcClient;
677: HANDLE hDefer;
678: DWORD wFlags;
679:
680: cWindows = CountWindows(hwndParent);
681:
682: if (!cWindows)
683: return;
684:
685: /* Compute the smallest nearest square. */
686: for (i=2; i * i <= cWindows; i++);
687:
688: cRows = i - 1;
689: cCols = cWindows / cRows;
690: cExtra = cWindows % cRows;
691:
692: GetClientRect(hwndParent, (LPRECT)&rcClient);
693: xRes = rcClient.right - rcClient.left;
694: yRes = rcClient.bottom - rcClient.top;
695:
696: if (xRes<=0 || yRes<=0)
697: return;
698:
699: hwndMove = GetWindow(hwndParent, GW_CHILD);
700:
701: hDefer = BeginDeferWindowPos(cWindows);
702:
703: for (iCol=0; iCol < cCols; iCol++) {
704: if ((cCols-iCol) <= cExtra)
705: cRows++;
706:
707: for (iRow=0; iRow < cRows; iRow++) {
708: dx = xRes / cCols;
709: dy = yRes / cRows;
710:
711: wFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS;
712:
713: /* Position and size the window. */
714: hDefer = DeferWindowPos(hDefer, hwndMove, NULL,
715: dx * iCol,
716: dy * iRow,
717: dx,
718: dy,
719: wFlags);
720:
721: hwndMove = GetWindow(hwndMove, GW_HWNDNEXT);
722: }
723:
724: if ((cCols-iCol) <= cExtra) {
725: cRows--;
726: cExtra--;
727: }
728: }
729:
730: EndDeferWindowPos(hDefer);
731:
732: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.