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