home *** CD-ROM | disk | FTP | other *** search
/ Dan Appleman's Visual Bas…s Guide to the Win32 API / Dan.Applmans.Visual.Basic.5.0.Programmers.Guide.To.The.Win32.API.1997.Ziff-Davis.Press.CD / VB5PG32.mdf / articles / vbdev / source / pindrag2.frm (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1996-01-22  |  16.4 KB  |  440 lines

  1. VERSION 4.00
  2. Begin VB.Form frmDrag 
  3.    Appearance      =   0  'Flat
  4.    BackColor       =   &H00FFFFFF&
  5.    Caption         =   "Dynamic Dragging Example"
  6.    ClientHeight    =   5760
  7.    ClientLeft      =   1095
  8.    ClientTop       =   1485
  9.    ClientWidth     =   7365
  10.    BeginProperty Font 
  11.       name            =   "MS Sans Serif"
  12.       charset         =   1
  13.       weight          =   700
  14.       size            =   8.25
  15.       underline       =   0   'False
  16.       italic          =   0   'False
  17.       strikethrough   =   0   'False
  18.    EndProperty
  19.    ForeColor       =   &H80000008&
  20.    Height          =   6165
  21.    Left            =   1035
  22.    LinkTopic       =   "Form1"
  23.    ScaleHeight     =   5760
  24.    ScaleWidth      =   7365
  25.    Top             =   1140
  26.    Width           =   7485
  27.    Begin VB.CommandButton Command1 
  28.       Appearance      =   0  'Flat
  29.       BackColor       =   &H80000005&
  30.       Caption         =   "Command1"
  31.       Height          =   555
  32.       Left            =   1380
  33.       TabIndex        =   4
  34.       Top             =   2400
  35.       Width           =   1335
  36.    End
  37.    Begin VBX.ccWinHook WinHook1 
  38.       Left            =   360
  39.       Messages        =   "PINDRAG2.frx":0000
  40.       Monitor         =   1  'My Siblings
  41.       Top             =   5040
  42.    End
  43.    Begin VB.TextBox Text1 
  44.       Appearance      =   0  'Flat
  45.       Height          =   855
  46.       Left            =   3240
  47.       MultiLine       =   -1  'True
  48.       TabIndex        =   3
  49.       Text            =   "PINDRAG2.frx":0406
  50.       Top             =   1380
  51.       Width           =   3135
  52.    End
  53.    Begin VB.PictureBox picDrag 
  54.       Appearance      =   0  'Flat
  55.       BackColor       =   &H00FFFFFF&
  56.       BorderStyle     =   0  'None
  57.       ForeColor       =   &H80000008&
  58.       Height          =   1695
  59.       Left            =   2160
  60.       ScaleHeight     =   1695
  61.       ScaleWidth      =   2595
  62.       TabIndex        =   0
  63.       Top             =   3240
  64.       Visible         =   0   'False
  65.       Width           =   2595
  66.    End
  67.    Begin VB.CheckBox chkDrag 
  68.       Appearance      =   0  'Flat
  69.       BackColor       =   &H80000005&
  70.       Caption         =   "Drag ""Design"" Mode On"
  71.       ForeColor       =   &H80000008&
  72.       Height          =   495
  73.       Left            =   4320
  74.       TabIndex        =   2
  75.       Top             =   120
  76.       Width           =   2835
  77.    End
  78.    Begin VB.PictureBox Picture2 
  79.       Appearance      =   0  'Flat
  80.       BackColor       =   &H0000FF00&
  81.       ForeColor       =   &H80000008&
  82.       Height          =   1575
  83.       Left            =   900
  84.       ScaleHeight     =   1545
  85.       ScaleWidth      =   1785
  86.       TabIndex        =   1
  87.       Top             =   540
  88.       Width           =   1815
  89.    End
  90. Attribute VB_Name = "frmDrag"
  91. Attribute VB_Creatable = False
  92. Attribute VB_Exposed = False
  93. Option Explicit
  94. ' Current drag state
  95. ' 0 - Drag mode is off
  96. ' 1 - Waiting on mouse down
  97. ' 2 - Sizing on CurrentHandle
  98. ' 3 - Moving
  99. Dim DragState%
  100. ' 1 to 8 - indicates current handle for cursor and sizing
  101. ' 0 means cursor is not over a handle
  102. ' 1   8   7
  103. ' 2       6
  104. ' 3   4   5
  105. Dim CurrentHandle%
  106. Const HandleSize% = 5
  107. ' Smallest drag size (minimum size of control when sizing)
  108. Const MinDragSizeX% = 10 ' pixels
  109. Const MinDragSizeY% = 10 ' pixels
  110. ' Size of grab handles in twips
  111. Dim HandleSizeTwipsX%
  112. Dim HandleSizeTwipsY%
  113. ' Handle rectangles (twips coordinates)
  114. Dim HandleRects(8) As Rect
  115. ' x and y reference point (previous position - pixel coordinates)
  116. Dim Anchor(2) As Integer
  117. Dim RefPoint(2) As Integer
  118. ' Current location of drag rectangle (pixel screen coordinates)
  119. Dim DragRect As Rect
  120. Dim ScreenDC%   ' Screen device context
  121. Dim UsePen%     ' Grey pen used for dragging
  122. ' Control that we are dragging or sizing
  123. Dim ControlToAdjust As Control
  124. ' Calculate the rectangles that describe the grab handles
  125. Private Sub CalcHandles()
  126.     Dim nleft%, ntop%
  127.     Dim x%
  128.     For x% = 1 To 8
  129.         Select Case x%
  130.                 Case 1  ' Upper left
  131.                         nleft% = 0
  132.                         ntop% = 0
  133.                 Case 2, 6 ' Center left
  134.                           ' Or center right
  135.                         ntop% = picDrag.Height \ 2 - HandleSizeTwipsY \ 2
  136.                 Case 3  ' Bottom left
  137.                         ntop% = picDrag.Height - HandleSizeTwipsY
  138.                 Case 4, 8   ' Bottom center
  139.                             ' Top center
  140.                         nleft% = picDrag.Width \ 2 - HandleSizeTwipsX \ 2
  141.                 Case 5  ' Bottom right
  142.                         nleft% = picDrag.Width - HandleSizeTwipsX
  143.                 Case 7  ' Upper right
  144.                         ntop% = 0
  145.         End Select
  146.         HandleRects(x%).top = ntop%
  147.         HandleRects(x%).left = nleft%
  148.         HandleRects(x%).right = nleft% + HandleSizeTwipsX
  149.         HandleRects(x%).bottom = ntop% + HandleSizeTwipsY
  150.     Next x%
  151. End Sub
  152. Private Sub chkDrag_Click()
  153.     Dim style&
  154.     Dim dl&
  155.     If chkDrag.Value = 1 Then
  156.         ' It's been clicked
  157.         
  158.         ' Place over control
  159.         Set ControlToAdjust = picture2
  160.         picDrag.Move -1, -1 ' Trick Windows into always moving control
  161.         PlacePicDrag ControlToAdjust
  162.         DragState = 1   ' Watch for mouse down
  163.     Else
  164.         picDrag.Visible = False
  165.         DragState = 0
  166.     End If
  167. End Sub
  168. Private Sub Command1_Click()
  169.     ' Notice - no beep in design mode!
  170.     Beep
  171. End Sub
  172. ' mode  0 - Start the drag
  173. '       1 - New position
  174. '       2 - End the drag
  175. Private Sub DragTheRect(ByVal mode%, ByVal x%, ByVal y%)
  176.     Dim di%
  177.     Static origpen%
  178.     Static newpen%
  179.     Select Case mode%
  180.         Case 0
  181.                 ' Get a device context for the screen
  182.                 ScreenDC% = CreateDC("Display", 0, 0, 0)
  183.                 ' XOR line draw mode
  184.                 di% = SetROP2(ScreenDC%, R2_XORPEN)
  185.                 ' Create a grey pen and select it
  186.                 newpen% = CreatePen(PS_SOLID, 3, QBColor(8))
  187.                 origpen% = SelectObject(ScreenDC%, newpen)
  188.                 ' Don't fill the rectangle
  189.                 di% = SelectObject(ScreenDC%, GetStockObject(NULL_BRUSH))
  190.                 ' Draw the first rectangle
  191.                 Rectangle ScreenDC%, DragRect.left, DragRect.top, DragRect.right, DragRect.bottom
  192.                 ' Mark the anchor point
  193.                 Anchor(1) = x%
  194.                 Anchor(2) = y%
  195.                 ' Set the original reference to the same point
  196.                 RefPoint(1) = x%
  197.                 RefPoint(2) = y%
  198.         Case 1  ' Called during movement
  199.                 ' Erase previous rectangle
  200.                 Rectangle ScreenDC%, DragRect.left, DragRect.top, DragRect.right, DragRect.bottom
  201.                 ' Now handle the new position
  202.                 If DragState = 3 Then
  203.                     ' Move the rectangle
  204.                     OffsetRect DragRect, x% - RefPoint(1), y% - RefPoint(2)
  205.                 Else ' DragState is 2 (sizing)
  206.                     ' Adjust the size based on the grab handle in use
  207.                     Select Case CurrentHandle
  208.                         Case 1 To 3
  209.                             DragRect.left = DragRect.left + x% - RefPoint(1)
  210.                         Case 5 To 7
  211.                             DragRect.right = DragRect.right + x% - RefPoint(1)
  212.                     End Select
  213.                     Select Case CurrentHandle
  214.                         Case 3 To 5
  215.                             DragRect.bottom = DragRect.bottom + y% - RefPoint(2)
  216.                         Case 1, 7 To 8
  217.                             DragRect.top = DragRect.top + y% - RefPoint(2)
  218.                     End Select
  219.                 End If
  220.                 ' Draw the new rectangle
  221.                 Rectangle ScreenDC%, DragRect.left, DragRect.top, DragRect.right, DragRect.bottom
  222.                 RefPoint(1) = x%
  223.                 RefPoint(2) = y%
  224.         Case 2  ' Clean up when done
  225.                 ' Erase previous rectangle
  226.                 Rectangle ScreenDC%, DragRect.left, DragRect.top, DragRect.right, DragRect.bottom
  227.                 ' Replace original pen
  228.                 di% = SelectObject(ScreenDC%, origpen)
  229.                 di% = DeleteObject(newpen)
  230.                 
  231.                 ' Destroy the device context
  232.                 di% = DeleteDC(ScreenDC%)
  233.                 ' Mark the final position.
  234.                 RefPoint(1) = x%
  235.                 RefPoint(2) = y%
  236.                 
  237.     End Select
  238. End Sub
  239. ' Draw the grab handles
  240. Private Sub DrawHandles()
  241.     Dim x%
  242.     For x% = 1 To 8
  243.         picDrag.Line (HandleRects(x%).left, HandleRects(x%).top)-Step(HandleSizeTwipsX, HandleSizeTwipsY), 0, BF
  244.     Next x%
  245. End Sub
  246. Private Sub Form_Load()
  247.     ' Set the size of the grab handles
  248.     HandleSizeTwipsX% = HandleSize * Screen.TwipsPerPixelX
  249.     HandleSizeTwipsY% = HandleSize * Screen.TwipsPerPixelY
  250. End Sub
  251. ' Find out which (if any) grab handle is under the specified point
  252. Private Function GetHandleForPoint%(ByVal x%, ByVal y%)
  253.     Dim n%
  254.     Dim pt&
  255.     pt& = (CLng(y%) * &H10000) Or x%
  256.     For n% = 1 To 8
  257.         If PtInRect(HandleRects(n%), pt&) Then
  258.             GetHandleForPoint = n
  259.             Exit Function
  260.         End If
  261.     Next n
  262.     ' It's not over a grab handle
  263.     GetHandleForPoint = 0
  264.         
  265. End Function
  266. ' Clicked on picture
  267. Private Sub picDrag_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
  268.     Dim di%
  269.     Select Case DragState%
  270.         Case 1  ' Waiting for the click
  271.                 ' We are now entering move or drag mode
  272.                 ' Hide the drag window
  273.                 picDrag.Visible = False
  274.                 ' Clip the cursors
  275.                 SetCursorClipping
  276.                 ' Grab the capture
  277.                 di% = SetCapture(picDrag.hwnd)
  278.                 
  279.                 ' Position the initial drag rectangle
  280.                 GetClientRect picDrag.hwnd, DragRect
  281.                 ClientToScreen picDrag.hwnd, DragRect.left
  282.                 ClientToScreen picDrag.hwnd, DragRect.right
  283.                 
  284.                 If CurrentHandle% = 0 Then
  285.                     ' It's a move
  286.                     DragState = 3
  287.                 Else
  288.                     ' It's a drag
  289.                     DragState = 2
  290.                 End If
  291.                 ' Initialize the dragging
  292.                 DragTheRect 0, x \ Screen.TwipsPerPixelX, y \ Screen.TwipsPerPixelY
  293.     End Select
  294. End Sub
  295. Private Sub picDrag_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
  296.     Dim newhandle%
  297.     Select Case DragState
  298.         Case 1  ' Normal mouse movement - Adjust cursor
  299.                 newhandle% = GetHandleForPoint(x, y)
  300.                 ' No change
  301.                 If newhandle% = CurrentHandle% Then Exit Sub
  302.                 Select Case newhandle%
  303.                     Case 0
  304.                         picDrag.MousePointer = 0
  305.                     Case 1, 5
  306.                         picDrag.MousePointer = 8
  307.                     Case 2, 6
  308.                         picDrag.MousePointer = 9
  309.                     Case 3, 7
  310.                         picDrag.MousePointer = 6
  311.                     Case 4, 8
  312.                         picDrag.MousePointer = 7
  313.                 End Select
  314.                 CurrentHandle% = newhandle%
  315.         
  316.         Case 2, 3 ' Dragging or sizing
  317.                 DragTheRect 1, x \ Screen.TwipsPerPixelX, y \ Screen.TwipsPerPixelY
  318.     End Select
  319. End Sub
  320. ' Mouse was released
  321. Private Sub picDrag_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
  322.     Dim di%
  323.     Select Case DragState%
  324.         Case 2, 3   ' Released after move or size
  325.                 DragTheRect 2, x \ Screen.TwipsPerPixelX, y \ Screen.TwipsPerPixelY
  326.                 
  327.                 ' Dump cursor clipping
  328.                 ClipCursorClear 0
  329.                 ' Release the capture
  330.                 ReleaseCapture
  331.                 ' Now convert DragRect into container coordinates
  332.                 ScreenToClient ControlToAdjust.Parent.hwnd, DragRect.left
  333.                 ScreenToClient ControlToAdjust.Parent.hwnd, DragRect.right
  334.                 DragRect.left = DragRect.left * Screen.TwipsPerPixelX
  335.                 DragRect.top = DragRect.top * Screen.TwipsPerPixelY
  336.                 DragRect.right = DragRect.right * Screen.TwipsPerPixelX
  337.                 DragRect.bottom = DragRect.bottom * Screen.TwipsPerPixelY
  338.                 ' We now have the new control size/location in container
  339.                 ' coordinates.  Set the new control position
  340.                 ControlToAdjust.Move DragRect.left, DragRect.top, DragRect.right - DragRect.left, DragRect.bottom - DragRect.top
  341.                 ' And place the dragging window over this one
  342.                 PlacePicDrag ControlToAdjust
  343.     End Select
  344. End Sub
  345. Private Sub picDrag_Paint()
  346.     ' We earlier ate the WM_ERASEBKGND message
  347.     ' Now draw the grab handles
  348.     DrawHandles
  349. End Sub
  350. ' Place the drag picture control over a control
  351. Private Sub PlacePicDrag(ctl As Control)
  352.     ' Place over control
  353.     Dim style&
  354.     Dim dl&
  355.     Dim nleft&, ntop&, nwidth&, nheight&
  356.     ' Position the drag control over the target control.
  357.     ' Make it large enough so the grab handles fit.
  358.     nleft& = ctl.left - HandleSizeTwipsX \ 2
  359.     ntop& = ctl.top - HandleSizeTwipsY \ 2
  360.     nwidth& = ctl.Width + HandleSizeTwipsX
  361.     nheight& = ctl.Height + HandleSizeTwipsY
  362.     ' Our drag picture control must be on top.
  363.     picDrag.ZOrder 0
  364.     ' Make it transparent
  365.     style& = GetWindowLong(picDrag.hwnd, GWL_EXSTYLE)
  366.     style& = style& Or WS_EX_TRANSPARENT
  367.     dl& = SetWindowLong(picDrag.hwnd, GWL_EXSTYLE, style&)
  368.     ' Note - be sure form ClipControls property is True
  369.     picDrag.Visible = True
  370.     picDrag.Move nleft&, ntop&, nwidth&, nheight&
  371.     CalcHandles     ' Calcuate grab handle positions
  372.     DragState = 1   ' Watch for mouse down
  373. End Sub
  374. ' Set the cursor clipping based on the current handle setting
  375. Private Sub SetCursorClipping()
  376.     Dim rcscreen As Rect
  377.     ' Start with a rectangle describing the form
  378.     GetClientRect frmDrag.hwnd, rcscreen
  379.     ' Now adjust per handle in use, Horizontal first
  380.     Select Case CurrentHandle
  381.         Case 0  ' Full screen, do nothing
  382.         Case 1 To 3
  383.             rcscreen.right = (picDrag.left + picDrag.Width) \ Screen.TwipsPerPixelX - MinDragSizeX
  384.         Case 5 To 7
  385.             rcscreen.left = picDrag.left \ Screen.TwipsPerPixelX + MinDragSizeX%
  386.     End Select
  387.     ' Now adjust the vertical dimension
  388.     Select Case CurrentHandle
  389.         Case 0  ' Full screen, do nothing
  390.         Case 3 To 5
  391.             rcscreen.top = picDrag.top \ Screen.TwipsPerPixelY + MinDragSizeX
  392.         Case 1, 7 To 8
  393.             rcscreen.bottom = (picDrag.top + picDrag.Height) \ Screen.TwipsPerPixelX - MinDragSizeX%
  394.     End Select
  395.     ' Now convert the rectangle to screen coordinates
  396.     ClientToScreen frmDrag.hwnd, rcscreen.left
  397.     ClientToScreen frmDrag.hwnd, rcscreen.right
  398.     ' And set the clipping
  399.     ClipCursorRect rcscreen
  400. End Sub
  401. ' Set to drag the next control
  402. Private Sub WinHook1_DelayedEvent(lvalue As Long)
  403.     picDrag.Visible = False
  404.     PlacePicDrag ControlToAdjust
  405. End Sub
  406. ' Select the control to drag or size
  407. Private Sub WinHook1_WndMessage(wnd As Integer, msg As Integer, wp As Integer, lp As Long, nodef As Integer)
  408.     Dim ctl As Control
  409.     Dim x%
  410.     Dim FoundHwnd%
  411.     Dim NotValid%
  412.     ' We are only concerned with DragState 1
  413.     If DragState% <> 1 Then Exit Sub
  414.     ' Ignore mouse clicks in picDrag
  415.     If wnd = picDrag.hwnd Then Exit Sub
  416.     ' Also ignore clicks on the checkbox that lets us
  417.     ' turn dragging off!
  418.     If wnd = chkDrag.hwnd Then Exit Sub
  419.     On Error GoTo HwndNotFound
  420.     For x% = 0 To frmDrag.Controls.Count - 1
  421.         FoundHwnd% = frmDrag.Controls(x%).hwnd
  422.         If Not NotValid% And wnd = FoundHwnd% Then
  423.             ' We are already handling this control
  424.             If wnd = ControlToAdjust.hwnd Then Exit Sub
  425.             WinHook1.PostEvent = 0
  426.             Set ControlToAdjust = frmDrag.Controls(x%)
  427.             nodef = True
  428.             msg = 0
  429.             Exit Sub
  430.         End If
  431.         NotValid% = False   ' Clear the flag
  432.     Next x%
  433.     ' Clear error correction
  434.     On Error GoTo 0
  435.     Exit Sub
  436. HwndNotFound:
  437.     NotValid% = True    ' Don't try to use this control
  438.     Resume Next
  439. End Sub
  440.