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