Solved

Couple of Quick ones

Posted on 2003-11-01
21
280 Views
Last Modified: 2010-05-01
three questions:

1) how can i make the mouse curser invisable?
2) if i have 3 forms(frmmain, frmsec and frmabout). on frmmain i click a button it loads frmabout and hides frmmain. I click a button on frmabout and it hides frmabout and shows frmmain. This is grade 1 stuff. then from frmsec i click a button and frm about is shown frmsec is hidden. BUT then i want to be able to push the same button on frmabout, which hide frmabout and showed frmmain and have frmsec show up and frmabout close...is it possible?
3) Using this code

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    linevert.X1 = X
    linevert.X2 = X
   
    linehor.Y1 = Y
    linehor.Y2 = Y

it is possible to get 2 lines to make a cross hair, it looks pretty cool the lines move with the curser. The problem is when you move the curser over an image or command button ect the lines stop until u move them back off the object. Anyone know how to fix this?
0
Comment
Question by:clownnames
  • 10
  • 9
  • 2
21 Comments
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 9663525
In answer to your second question.  Create a new project and add two forms.  Place two buttons on the first form, two buttons on the second form, and one button on the third form.  Paste the code onto the forms and run it.

' ------------------------------------------   On Form1
Private Sub Form_Load()
    Command1.Caption = "Form2"
    Command2.Caption = "About"
End Sub

Private Sub Command1_Click()
    Me.Hide
    Form2.Show
End Sub

Private Sub Command2_Click()
    Load Form3
    Set Form3.callingForm = Me
    Me.Hide
    Form3.Show
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Unload Form2
    Unload Form3
End Sub

' ------------------------------------------   On Form2
Private Sub Form_Load()
    Command1.Caption = "Form1"
    Command2.Caption = "About"
End Sub

Private Sub Command1_Click()
    Me.Hide
    form1.Show
End Sub

Private Sub Command2_Click()
    Load Form3
    Set Form3.callingForm = Me
    Me.Hide
    Form3.Show
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Unload Form3
    Unload form1
End Sub

' ------------------------------------------   On Form3
Public callingForm As Form

Private Sub Form_Load()
    Command1.Caption = "OK"
End Sub

Private Sub Command1_Click()
    Me.Hide
    callingForm.Show
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Me.Hide
    callingForm.Show
End Sub
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 9663588
To hide the cursor you have to use an API.   On your form:

Private Declare Function ShowCursor Lib "User32" (ByVal bShow As Integer) As Integer

Private Sub Form_Load()
    'Hide the cursor
    Do While ShowCursor(False) >= 0
    Loop
End Sub

Private Sub Form_Unload(Cancel As Integer)
    ' Show the cursor again...
    ' if you don't do this...no apps will have a cursor!
    Do While ShowCursor(True) < 0
    Loop
End Sub
0
 

Author Comment

by:clownnames
ID: 9664483
I get this error when i try hide the cursor, whats an API?

Run-time error '453'

Can't find DLL entry point Showcursor in User 32
0
 

Author Comment

by:clownnames
ID: 9665213
or when i moved it in the code

file not found user 32
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 9665294
It should be User32 with no space.  What version windows you running?
0
 

Author Comment

by:clownnames
ID: 9665417
Run-time error '453'

Can't find DLL entry point Showcursor in User32

didnt fix, im running xp professional edition, but the program needs to be compatable with all operating systems.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 9665906
I'm running WinMe and the ShowCursor function works great.  I will look into what needs to be done for XP.
0
 

Author Comment

by:clownnames
ID: 9667378
thanx
0
 
LVL 5

Expert Comment

by:fantasy1001
ID: 9668056
This works fine for window xp,
add this to the top of the main form code where this api will be called
Private Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As Long

' usage
showcursor 0   'hide cursor
showcursor 1   'show cursor

regards,
~ fantasy ~
0
 

Author Comment

by:clownnames
ID: 9668737
Thanx guys

using Private Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As Long

and

    Do While ShowCursor(False) >= 0
    Loop

worked

but showcursor 0 and 1 didnt.

any1 know how to fix the third problem i have with the lines not moveing over other objects?
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 5

Expert Comment

by:fantasy1001
ID: 9669025
What's the Error shown when you call showcursor 0 or showcursor 1

'I have this example showing/hiding the cursor
Private Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As Long
Private Sub Form_Load()
    'Hide the cursor
    ShowCursor 0
    'Wait 10 seconds
    t = Timer
    Do: DoEvents: Loop Until Timer > t + 10
    'Show the cursor
    ShowCursor 1
End Sub

~ fantasy ~
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 9670830
fantasy1001, there probably is no error when ShowCursor 0 or ShowCursor 1 is used.  That code may or may not work.  The cursor is displayed or not displayed based upon an internal counter maintained by windows.  Each time you use ShowCursor 1, the counter is incremented.  Each time you use ShowCursor 0, the counter is decremented.  If the counter is >=0 then the cursor will show.  If it goes below zero, then it will not show.  To ensure your mouse hiding/unhiding code works on all systems, you must use the loop:

    'Hide the cursor
    Do While ShowCursor(False) >= 0
    Loop

    ' Show the cursor again...
    Do While ShowCursor(True) < 0
    Loop

0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 9670919
Here is a solution to your third question.  The lines don't actually draw over objects, but you can keep the lines moving behind them and turn the cursor back on.  Try this code and see how you like the effect.  Create a new project and add a commandbutton and a textbox.  Paste the code and hit run.  The button can be clicked to exit.

Private Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As Long

Private Sub Form_Load()
    ShowPointer False
    Command1.Caption = "Exit"
End Sub

Private Sub Command1_Click()
    Unload Me
End Sub

Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Form_MouseMove Button, Shift, Command1.Left + X, Command1.Top + Y
    ShowPointer True
End Sub

Private Sub Text1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Form_MouseMove Button, Shift, Text1.Left + X, Text1.Top + Y
    ShowPointer True
End Sub

Private Sub ShowPointer(pointer As Boolean)
    If pointer Then
        Do While ShowCursor(1) < 0
            DoEvents
        Loop
    Else
        Do While ShowCursor(0) >= 0
            DoEvents
        Loop
    End If
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    ShowPointer False
    Line1.X1 = X
    Line1.X2 = X
    Line2.Y1 = Y
    Line2.Y2 = Y
End Sub

Private Sub Form_Resize()
    Line1.Y1 = 0
    Line1.Y2 = Me.Height
    Line2.X1 = 0
    Line2.X2 = Me.Width
End Sub

Private Sub Form_Unload(Cancel As Integer)
    ShowPointer True
End Su
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 9670936
sorry, you also need to add two lines to your project.
0
 

Author Comment

by:clownnames
ID: 9676610
yeah showcursor 1 and 0 dont give an error they just dont do anything.

and i am actually planning on haveing about 100 labels on a form and having the lines go behind the labels doesnt look all that good. It would be ok if i was only gonna have a few labels but 100 is 2 many thanx 4 trying thou
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 9684614
clownnames,

Here is a solution to your third question.  It proved to be quite challenging and in my opinion is worth way more than the points allotted.

Before we get to the code, a little explanation on how to draw on controls is warranted.  There are two types of controls in VB 6.0: Regular and Lightweight.

A Regular control has its own window and the operating system maintains a handle to it.  The control (button, textbox, radiobutton, etc) is then drawn on this window.  This is why your lines did not draw over your button, because it is actually another window floating over your form.

A Lightweight control does not have its own window.  It is drawn directly onto its container.  The most common lightweight controls are the image, shape, line and label controls.

To draw on the controls you must first get a Device Context to draw on.  Conceptually, a device context is a link between a Windows-based application, a device driver, and an output device such as a display, printer, or plotter.

All the regular controls expose the hWnd property, which is the handle to its window.  You can then use the GetDC API to get the device context from the window handle.  Once this is done, you can pass the device context to a myriad of drawing API's (most of which are in the gdi32.dll).  In this example, we only used the moveto and line API's.  There are other drawing API's to make circles, ellipses, rectangles, images, etc.  Using these same techniques you could display an image on any of the controls.

Since the lightweight controls do not have windows, they also do not have a device contexts.  To get around this, you simply use the lightweight controls container, usually the form itself, to obtain the device context to draw on.  You then simply use the controls position to calculate where to draw on the form so that the drawing is offset onto the control.

With that out the way, let's move on to the problem of trapping mouse movement.  There are two kinds of movement to deal with: Movement on the form, and Movement within a control.

When movement on the form is detected, you must draw your lines at the current x, y positions.  As you already know though, the lines will not go over any controls on the form.   The solution is to walk the controls collection from the form and determine whether or not the lines intersect any of them.  If a control is in the path of one of the lines, then a line is drawn on the control itself, giving the illusion that the lines on the form are drawing right over them.

When movement within a control is detected, you must do everything that was done for movement on the form, as well as draw both lines inside the control.

The code for movement on the form is generic, and since we can access all controls from the controls collection, will work no matter how many controls you add to the form.

The code for movement within a control is not generic however.  You must manually add code to the mouse move event for each control you add to your form.  There may be a way to eliminate this duplication of code with subclassing but I'm not sure how to do that, and it would certainly add to the complexity of the project.

If the control is a lightweight control, you must add code that looks like this:
Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    Form_MouseMove Button, Shift, Label1.Left + x, Label1.Top + y
End Sub

If the control is a regular control then add code like this:
Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    HeavyweightMouseMove Command1, x, y
End Sub

This must be done for each control you add, or the lines will stop moving when the mouse passes over that control.  Be sure to type the names of the controls in correctly or it wont work.  (note Label1 and Command1 in the code)

So without further adieu...here is the code.  Create a project and add a label, a button and a textbox.  You do not have to add any lines.

Option Explicit

Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, lpPoint As Any) As Long
Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As Long

Private Sub Form_Load()
    ShowPointer False
    Command1.Caption = "Exit"
End Sub

Private Sub Command1_Click()
    Unload Me
End Sub

Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    Form_MouseMove Button, Shift, Label1.Left + x, Label1.Top + y
End Sub

Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    HeavyweightMouseMove Command1, x, y
End Sub

Private Sub Text1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    HeavyweightMouseMove Text1, x, y
End Sub

Private Sub HeavyweightMouseMove(control As control, x As Single, y As Single)
    refreshAllControls
    updateFormLines control.Left + x, control.Top + y
    drawOnControl control, x, y
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    refreshAllControls
    updateFormLines x, y
    drawControlLines x, y
End Sub

Private Sub refreshAllControls()
    On Error Resume Next
    ' Redraw all controls to get rid of any lines on them
    Dim curcontrol As Object
    For Each curcontrol In Me.Controls
        curcontrol.Refresh
    Next curcontrol
End Sub

Private Sub updateFormLines(x As Single, y As Single)
    ' Draw lines on form
    Dim TemporaryHandle As Long
    TemporaryHandle = GetDC(Me.hWnd)
    Me.Cls
    MoveToEx TemporaryHandle, 0, y \ Screen.TwipsPerPixelY, ByVal 0&
    LineTo TemporaryHandle, Me.Width \ Screen.TwipsPerPixelX, y \ Screen.TwipsPerPixelY
    MoveToEx TemporaryHandle, x \ Screen.TwipsPerPixelX, 0, ByVal 0&
    LineTo TemporaryHandle, x \ Screen.TwipsPerPixelX, Me.Height \ Screen.TwipsPerPixelY
End Sub

Private Sub drawControlLines(x As Single, y As Single)
    ' Draw lines on controls if appropriate
    On Error Resume Next
    Dim curcontrol As Variant
    Dim cx As Single, cy As Single
    For Each curcontrol In Me.Controls
        If Not (TypeOf curcontrol Is Line) Then
            If Not (TypeOf curcontrol Is Label) Then
                cx = (x - curcontrol.Left) \ Screen.TwipsPerPixelX
                cy = (y - curcontrol.Top) \ Screen.TwipsPerPixelY
                If x >= curcontrol.Left And x <= curcontrol.Left + curcontrol.Width Then
                    drawOnControlVertical curcontrol, cx, cy
                ElseIf y >= curcontrol.Top And y <= curcontrol.Top + curcontrol.Height Then
                    drawOnControlHorizontal curcontrol, cx, cy
                End If
            Else
                If x >= curcontrol.Left And x <= curcontrol.Left + curcontrol.Width Then
                    drawOnLabelVertical Me, x, y
                ElseIf y >= curcontrol.Top And y <= curcontrol.Top + curcontrol.Height Then
                    drawOnLabelHorizontal Me, x, y
                End If
            End If
        End If
    Next curcontrol
End Sub

Private Sub drawOnLabelHorizontal(ByRef control As Label, x As Single, y As Single)
    Dim TemporaryHandle As Long
    TemporaryHandle = GetDC(Me.hWnd)
    MoveToEx TemporaryHandle, 0, y, ByVal 0&
    LineTo TemporaryHandle, control.Left + control.Width, y
End Sub

Private Sub drawOnLabelVertical(ByRef control As Label, x As Single, y As Single)
    Dim TemporaryHandle As Long
    TemporaryHandle = GetDC(Me.hWnd)
    MoveToEx TemporaryHandle, x, 0, ByVal 0&
    LineTo TemporaryHandle, x, control.Top + control.Height
End Sub

Private Sub drawOnControl(ByRef control As Variant, x As Single, y As Single)
    drawOnControlHorizontal control, x, y \ Screen.TwipsPerPixelY
    drawOnControlVertical control, x \ Screen.TwipsPerPixelX, y
End Sub

Private Sub drawOnControlHorizontal(ByRef control As Variant, x As Single, y As Single)
    Dim TemporaryHandle As Long
    TemporaryHandle = GetDC(control.hWnd)
    MoveToEx TemporaryHandle, 0, y, ByVal 0&
    LineTo TemporaryHandle, control.Width \ Screen.TwipsPerPixelX, y
End Sub

Private Sub drawOnControlVertical(ByRef control As Variant, x As Single, y As Single)
    Dim TemporaryHandle As Long
    TemporaryHandle = GetDC(control.hWnd)
   
    MoveToEx TemporaryHandle, x, 0, ByVal 0&
    LineTo TemporaryHandle, x, control.Height \ Screen.TwipsPerPixelY
End Sub

Private Sub ShowPointer(pointer As Boolean)
    If pointer Then
        Do While ShowCursor(1) < 0
            DoEvents
        Loop
    Else
        Do While ShowCursor(0) >= 0
            DoEvents
        Loop
    End If
End Sub

Private Sub Form_Unload(Cancel As Integer)
    ShowPointer True
End Sub
0
 

Author Comment

by:clownnames
ID: 9685425
thats phyco THANX so much, i wish i could give u more points but i only get like 5 a day, is there any other way i can give u points?
0
 

Author Comment

by:clownnames
ID: 9686279
i have an array of labels and its not working properly
0
 

Author Comment

by:clownnames
ID: 9686432
its also created a bug from my second question using the callingForm  function, i got it almost fixed the only problem now is when i click on the about form, from the form with the cross hair, and click the ok on the about form the cursor stays visible. all i got to do is put

If frmcrosshair.open then
ShowPointer false
end if

except what can i put instead of frmcrosshair.open?
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 65 total points
ID: 9687042
Don't worry about the points, it was a great learning experience for me as well.

Change the two subs below so they have this code instead.

Private Sub drawControlLines(X As Single, Y As Single)
    ' Draw lines on controls if appropriate
    On Error Resume Next
    Dim curcontrol As Variant
    Dim cx As Single, cy As Single
    For Each curcontrol In Me.Controls
        If Not (TypeOf curcontrol Is Line) Then
            If Not (TypeOf curcontrol Is Label) Then
                cx = (X - curcontrol.Left) \ Screen.TwipsPerPixelX
                cy = (Y - curcontrol.Top) \ Screen.TwipsPerPixelY
                If X >= curcontrol.Left And X <= curcontrol.Left + curcontrol.Width Then
                    drawOnControlVertical curcontrol, cx, cy
                End If
                If Y >= curcontrol.Top And Y <= curcontrol.Top + curcontrol.Height Then
                    drawOnControlHorizontal curcontrol, cx, cy
                End If
            Else
                If X >= curcontrol.Left And X <= curcontrol.Left + curcontrol.Width Then
                    drawOnLabelVertical Me, X, Y
                End If
                If Y >= curcontrol.Top And Y <= curcontrol.Top + curcontrol.Height Then
                    drawOnLabelHorizontal Me, X, Y
                End If
            End If
        End If
    Next curcontrol
End Sub

Private Sub HeavyweightMouseMove(control As control, X As Single, Y As Single)
    refreshAllControls
    updateFormLines control.Left + X, control.Top + Y
    drawControlLines control.Left + X, control.Top + Y
End Sub

After changing those two subs, you can delete the drawOnControl() sub as it is no longer needed.

This is how you would handle an array of controls.  There is simply an extra parameter, index, passed in to the mouse move event (or any other event for that matter), which tells you which control in the array fired the event.

Private Sub Label1_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
    Form_MouseMove Button, Shift, Label1(Index).Left + X, Label1(Index).Top + Y
End Sub

Can you explain what is going on with the about form a little better?  Do yo want the normal cursor back on the about form? ... or did you want the lines on it as well?

Idle_Mind

0
 

Author Comment

by:clownnames
ID: 9712879
nah its all good now thanx tons
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now