I'm still messing about with drawing Entity Relationship diagrams and it occurred to me that maybe my basic method of drawing lines between boxes, resulting from trial and error, could be improved upon. So here is an example of the approach which I am using, can it be done better?
The code below will compile with version 9, and I would guess with version 8 too.
The code below will compile with version 9, and I would guess with version 8 too.
Code:
' ' demonstrating a way of redrawing lines between moveable/sizeable dialogs ' and hoping there is a better one! ' Chris Holbrook Sep 2008 ' ' (gripper code after an example by Jules Marchildon) ' #COMPILE EXE #DIM ALL #INCLUDE "WIN32API.INC" %IDD_DIALOG1 = 101 TYPE tCC hWnd AS DWORD r(0 TO 7) AS RECT hitval(0 TO 7) AS DWORD 'NCHITTEST return value centreX AS LONG centreY AS LONG END TYPE '---------------------------------------------------------------------- GLOBAL ghd() AS tcc GLOBAL gparentdlg AS DWORD '---------------------------------------------------------------------- SUB FigureHandleSizes(BYVAL hWnd AS LONG) LOCAL rc AS RECT LOCAL dx, dy, x, y, lcx AS LONG LOCAL dWHitValue AS DWORD LOCAL iIndex AS LONG GLOBAL ghd() AS tcc IF ghd(0).hwnd = hwnd THEN lcx = 0 ELSEIF ghd(1).hwnd = hwnd THEN lcx = 1 ELSE lcx = 2 END IF '**Get the width and height of the window frame ' we want to put handles on. dx = GetSystemMetrics(%SM_CXFRAME) dy = GetSystemMetrics(%SM_CYFRAME) + 1 'not sure why add 1 ??? CALL GetWindowRect(hWnd,rc) x = rc.nleft y = (rc.ntop + rc.nbottom) \ 2 - y \ 2 CALL MakeHandle(lcx, 0, rc.nleft, (rc.ntop + rc.nbottom) \ 2 - dy \ 2, dx, dy,%HTLEFT) CALL MakeHandle(lcx, 1, rc.nright-dx-1, (rc.ntop+rc.nbottom) \ 2-dy \ 2, dx, dy,%HTRIGHT) CALL MakeHandle(lcx, 2, (rc.nleft+rc.nright) \ 2-dx \ 2, rc.ntop, dx, dy,%HTTOP) CALL MakeHandle(lcx, 3, rc.nleft, rc.ntop, dx, dy,%HTTOPLEFT) CALL MakeHandle(lcx, 4, rc.nright-dx-1, rc.ntop, dx, dy,%HTTOPRIGHT) CALL MakeHandle(lcx, 5, (rc.nleft+rc.nright) \ 2-dx \ 2, rc.nbottom-dy-2, dx, dy,%HTBOTTOM) CALL MakeHandle(lcx, 6, rc.nleft, rc.nbottom-dy-2, dx, dy,%HTBOTTOMLEFT) CALL MakeHandle(lcx, 7, rc.nright-dy, rc.nbottom-dy-2, dx, dy,%HTBOTTOMRIGHT) END SUB '---------------------------------------------------------------------------------- SUB MakeHandle(lcx AS LONG, _ BYVAL iIndex AS LONG, _ BYVAL x AS LONG, _ BYVAL y AS LONG, _ BYVAL dx AS LONG, _ BYVAL dy AS LONG, _ BYVAL dwHitValue AS WORD) 'DIM Grips(0:7) AS tGRIPPERS GHD(lcx).r(iIndex).nleft = x GHD(lcx).r(iIndex).ntop = y GHD(lcx).r(iIndex).nright = x+dx+1 'adjust size GHD(lcx).r(iIndex).nbottom = y+dy+1 'adjust size GHD(lcx).hitval(iIndex) = dwHitValue END SUB '------------------------------------------------------------------------------ SUB ScreenToClientRect(BYVAL hWnd AS LONG, prRect AS RECT) LOCAL pt AS POINTAPI pt.x = prRect.nleft pt.y = prRect.ntop ScreenToClient hWnd,pt prRect.nleft = pt.x prRect.ntop = pt.y pt.x = prRect.nright pt.y = prRect.nbottom ScreenToClient hWnd,pt prRect.nright = pt.x prRect.nbottom = pt.y END SUB '------------------------------------------------------------------------------------ CALLBACK FUNCTION BoxCBProc() LOCAL ps AS PAINTSTRUCT LOCAL rc AS RECT LOCAL hdc, hbrush AS DWORD LOCAL i, lcx, lresult AS LONG LOCAL pt AS POINTAPI STATIC hparent AS DWORD SELECT CASE CBMSG CASE %WM_PAINT hdc = beginpaint(CBHNDL, PS) getwindowrect( CBHNDL, rc) ' draw outline of bos Rectangle hDC, 0, 0, rc.nright - rc.nleft , rc.nbottom - rc.ntop Rectangle hDC, 0, 0, rc.nright - rc.nleft , rc.nbottom - rc.ntop IF ghd(0).hwnd = CBHNDL THEN lcx = 0 ELSEIF ghd(1).hwnd = CBHNDL THEN lcx = 1 ELSE lcx = 2 END IF ' locate grippers... FigureHandleSizes CBHNDL '... and draw grippers FOR i = 0 TO 7 rc = GHD(lcx).r(i) ScreenToClientRect CBHNDL, rc FillRect hDC,rc,GetStockObject(%LTGRAY_BRUSH) NEXT endpaint(CBHNDL, ps) CASE %WM_LBUTTONDOWN SendMessage CBHNDL, %WM_NCLBUTTONDOWN, %HTCAPTION, BYVAL %NULL ' force drag CASE %WM_EXITSIZEMOVE DIALOG SEND gparentdlg, %WM_USER + 400, 0, 0 CASE %WM_NCHITTEST FigureHandleSizes CBHNDL IF ghd(0).hwnd = CBHNDL THEN lcx = 0 ELSEIF ghd(1).hwnd = CBHNDL THEN lcx = 1 ELSE lcx = 2 END IF GetClientRect CBHNDL,rc pt.x = LOWRD(CBLPARAM) pt.y = HIWRD(CBLPARAM) '**First, test for the "handles" FOR i = 0 TO 7 rc = ghd(lcx).r(i) lresult = PtInRect( rc, pt.x, pt.y ) IF lresult <> 0 THEN FUNCTION = ghd(lcx).hitval(i) EXIT FUNCTION END IF NEXT '**Second, test for moving ScreenToClient CBHNDL,pt lresult = PtInRect(rc, pt.x, pt.y) IF lresult = 0 THEN FUNCTION = %HTCAPTION 'force drag END SELECT END FUNCTION '------------------------------------------------------------------------------------ FUNCTION createboxes ( hParent AS DWORD) AS LONG LOCAL i AS LONG DIM ghd(0 TO 2) AS GLOBAL tcc FOR i = 0 TO 2 DIALOG NEW hParent, "", 80 * i + 20, 20 * i + 20, 50, 50, _ %WS_POPUP OR %WS_CHILD OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_NOFAILCREATE OR _ OR %DS_3DLOOK %DS_SETFONT , %WS_EX_TRANSPARENT OR %WS_EX_CONTROLPARENT OR _ OR %WS_EX_TOOLWINDOW %WS_EX_TOPMOST OR %WS_EX_LEFT OR %WS_EX_LTRREADING TO ghD(i).hWnd DIALOG SHOW MODELESS ghD(i).hWnd, CALL BoxCBProc 'TO lRslt NEXT END FUNCTION '------------------------------------------------------------------------------------ CALLBACK FUNCTION ShowDIALOG1Proc() LOCAL ps AS PAINTSTRUCT LOCAL r, rc AS RECT LOCAL hdc, hbrush, hpen AS DWORD LOCAL s AS STRING LOCAL i, lcx, lresult AS LONG LOCAL pt, p1, p2 AS POINTAPI SELECT CASE AS LONG CBMSG CASE %WM_INITDIALOG createboxes(CBHNDL) CASE %WM_USER + 400 BEEP getclientrect(CBHNDL,r) invalidaterect ( CBHNDL, BYREF r, %false) ' CASE %WM_EXITSIZEMOVE ' DIALOG SEND CBHNDL, %WM_USER + 400, 0, 0 CASE %WM_PAINT hdc = beginpaint(CBHNDL, PS) ' draw some background stuff s = REPEAT$(200, "oooooooo ") setrect rc, 0, 0, 500,500 drawtext hdc, BYVAL STRPTR(s), BYVAL LEN(s) + 1, BYVAL VARPTR(rc), %dt_wordbreak ' draw a line between the centres of the subdialogs hpen = selectobject(hdc, createpen(%PS_SOLID,2,%RED)) FOR i = 0 TO 2 ' for each subdialog getclientrect ghd(i).hwnd, BYREF r p1.x = r.nleft: p1.y = r.ntop p2.x = r.nright: p2.y = r.nbottom clienttoscreen ghd(i).hwnd, p1 clienttoscreen ghd(i).hwnd, p2 screentoclient CBHNDL, p1 screentoclient CBHNDL, p2 ghd(i).centrex = (p1.x + p2.x) \2 ghd(i).centrey = (p1.y + p2.y) \2 NEXT moveto hdc, ghd(0).centrex, ghd(0).centrey lineto hdc, ghd(1).centrex, ghd(1).centrey lineto hdc, ghd(2).centrex, ghd(2).centrey hpen = selectobject(hdc,hpen) deleteobject(hpen) endpaint(CBHNDL, ps) END SELECT END FUNCTION '------------------------------------------------------------------------------------ FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG LOCAL lRslt AS LONG LOCAL hDlg AS DWORD DIALOG NEW hParent, "lines & boxes question by Chris Holbrook", _ 193, 132, 262, 161, _ %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR _ %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _ %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR _ %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, _ TO gParentdlg DIALOG SHOW MODAL gparentdlg, CALL ShowDIALOG1Proc TO lRslt FUNCTION = lRslt END FUNCTION '------------------------------------------------------------------------------------ FUNCTION PBMAIN() DIM ghd(0 TO 0) AS tcc ShowDIALOG1 %HWND_DESKTOP END FUNCTION