-
[RESOLVED] scroll MDI Container with mouse wheel???
Ok so here's the situation. I have a mdi container with a child form inside of it. The child forms is longer than the mdi container which creates a vertical scroll bar.
Is there any way to scroll the mdi container with the mouse wheel. So far I cannot get it working. I want to be able to scroll it with the mouse wheel, not just manually (point, click, drag). Any ideas??
Thanks guys! :wave: Any help would be appreciated!
-
Re: scroll MDI Container with mouse wheel???
-
Re: scroll MDI Container with mouse wheel???
Im not sure if this works with a child Form, but you can try, take a look at This thread in the codebank by Bushmobile
-
Re: scroll MDI Container with mouse wheel???
thanks jcis! :thumb:
I will check it out!
EDIT:
If anyone else has any other ideas, please post. I do not think the script that jcis linked to will work with MDI child and parent forms.
-
Re: scroll MDI Container with mouse wheel???
I've decided to post this here (rather than the codebank thread) so more people will see it and possibly come up with a solution to another problem that gets generated.
It seems that as long as the ActiveControl isn't one which already responds to the mousewheel (textbox/combobox/etc.) then the WM_MOUSEWHEEL is sent to the MDIForm and we just have to do some simple subclassing and then we can move the child form accordingly.
However - the MDIForm scrollbar won't change it's position relative to the movement of the form - and I can't, for the life of me, get it to refresh without resorting to resizing the whole MDIForm which is obvious to the user.
Anyway - here's the code:
VB Code:
' In MDIForm
Option Explicit
Private Sub MDIForm_Load()
Call WheelHook(Me.hwnd)
End Sub
Public Sub MouseWheel(ByVal MouseKeys As Long, ByVal Rotation As Long, ByVal Xpos As Long, ByVal Ypos As Long)
Const lScrollAmount As Long = 180
With Me.ActiveForm
If Rotation > 0 Then
If .Top < 0 Then .Top = .Top + lScrollAmount
If .Top > 0 Then .Top = 0
Else
If .Top + .Height > Me.ScaleHeight Then .Top = .Top - lScrollAmount
If .Top + .Height < Me.ScaleHeight Then .Top = Me.ScaleHeight - .Height
End If
' Refresh the scrollbar here - but how???????????
End With
End Sub
Private Sub MDIForm_Unload(Cancel As Integer)
Call WheelUnHook(Me.hwnd)
End Sub
' In Module
Option Explicit
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" ( _
ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Const GWL_WNDPROC = -4
Private Const WM_MOUSEWHEEL = &H20A
Private lPrevProc As Long
' Check Messages
' ================================================
Private Function WindowProc(ByVal Lwnd As Long, ByVal Lmsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim MouseKeys As Long, Rotation As Long, Xpos As Long, Ypos As Long
Select Case Lmsg
Case WM_MOUSEWHEEL
MouseKeys = wParam And 65535
Rotation = wParam / 65536
Xpos = lParam And 65535
Ypos = lParam / 65536
MDIForm1.MouseWheel MouseKeys, Rotation, Xpos, Ypos
End Select
WindowProc = CallWindowProc(lPrevProc, Lwnd, Lmsg, wParam, lParam)
End Function
' Hook / UnHook
' ================================================
Public Sub WheelHook(ByVal hwnd As Long)
On Error Resume Next
lPrevProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Public Sub WheelUnHook(ByVal hwnd As Long)
On Error Resume Next
SetWindowLong hwnd, GWL_WNDPROC, lPrevProc
End Sub
Edit: Just incase you weren't aware - this code (since it uses subclassing) will crash the IDE and you'll lose any unsaved work if you press the Stop button - unload the form correctly and you'll have no trouble & remember to save!
-
Re: scroll MDI Container with mouse wheel???
i have used subclassing code to scoll a frame and that works correctly, but have not tried it on an mdi form,
on my computer i use either intellimouse, or freewheel, as they allow me to scroll all the windows in vb ide and some other programs that don't support scroll wheel.
i just tested freewheel on an mdi form and it works correctly
intellimouse (from microsoft) must be versions 4 (not later), also this clashes with touchpad drivers on my notebook
freewheel works fine on my notebook and is available free
pete
i have just tested the mousewheel code in a mdi form and it seems to work ok, but i have no idea what the difference is, so here it is courtesy of MS.
i took out the code to move the vertical scroll bar i had for the frame
in the child form
VB Code:
Private Sub Form_Load()
WheelHook Me
End Sub
Private Sub Form_Unload(Cancel As Integer)
WheelUnHook
End Sub
in the module
VB Code:
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" ( _
ByVal lpPrevWndFunc As Long, _
ByVal hWnd As Long, _
ByVal Msg As Long, _
ByVal Wparam As Long, _
ByVal Lparam As Long) As Long
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" ( _
ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Const MK_CONTROL = &H8
Public Const MK_LBUTTON = &H1
Public Const MK_RBUTTON = &H2
Public Const MK_MBUTTON = &H10
Public Const MK_SHIFT = &H4
Private Const GWL_WNDPROC = -4
Private Const WM_MOUSEWHEEL = &H20A
Dim LocalHwnd As Long
Dim LocalPrevWndProc As Long
Dim MyForm As Form
Private Function WindowProc(ByVal Lwnd As Long, ByVal Lmsg As Long, ByVal Wparam As Long, ByVal Lparam As Long) As Long
Dim MouseKeys As Long
Dim Rotation As Long
Dim Xpos As Long
Dim Ypos As Long
If Lmsg = WM_MOUSEWHEEL Then
MouseKeys = Wparam And 65535
Rotation = Wparam / 65536
Xpos = Lparam And 65535
Ypos = Lparam / 65536
' MyForm.mousewheel MouseKeys, Rotation, Xpos, Ypos 'code on form to move scroll bar, not required for mdi form
End If
WindowProc = CallWindowProc(LocalPrevWndProc, Lwnd, Lmsg, Wparam, Lparam)
End Function
Public Sub WheelHook(PassedForm As Form)
On Error Resume Next
Set MyForm = PassedForm
LocalHwnd = PassedForm.hWnd
LocalPrevWndProc = SetWindowLong(LocalHwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Public Sub WheelUnHook()
Dim WorkFlag As Long
On Error Resume Next
WorkFlag = SetWindowLong(LocalHwnd, GWL_WNDPROC, LocalPrevWndProc)
Set MyForm = Nothing
End Sub
-
Re: scroll MDI Container with mouse wheel???
Quote:
Originally Posted by bushmobile
I've decided to post this here (rather than the codebank thread) so more people will see it and possibly come up with a solution to another problem that gets generated.
It seems that as long as the ActiveControl isn't one which already responds to the mousewheel (textbox/combobox/etc.) then the WM_MOUSEWHEEL is sent to the MDIForm and we just have to do some simple subclassing and then we can move the child form accordingly.
However - the MDIForm scrollbar won't change it's position relative to the movement of the form - and I can't, for the life of me, get it to refresh without resorting to resizing the whole MDIForm which is obvious to the user.
Edit: Just incase you weren't aware - this code (since it uses subclassing) will crash the IDE and you'll lose any unsaved work if you press the Stop button - unload the form correctly and you'll have no trouble & remember to save!
Hey bushmobile,
I just tested out your code and it works!!! The vertical scrollbar DOES refresh, but only when you move your mouse outside the mdi form. Also, one thing I noticed is it scrolls the child even if it's smaller than the parent. What I mean is, even if there is no vertical scrollbar, it still scrolls the child, which is not necessary.
I will take a look at the code and see what I can do with it. I will also try out the FreeWheel and/or MS Intellipoint app that westconn1 suggested. I would honestly rather install a small mouse driver to fix the problem rather than add some code that may or may not cause other conflicts with my application.
Again i will test both ways and see which works better. Although I am not sure if westconn1 understands what I was looking for. I don't need to be able to scroll in the vb IDE. There is actually a fix from microsoft to fix the vb6 IDE scroll wheel problem here, which also suggests to install Intellipoint v4.12. But I will try intellipoint and freewheel to see if it works with scrolling an mdi parent and child form.
EDIT:
hahaha I figured out a SUPER ghetto way of refreshing the scrollbar. Actually it's stupid and pointless, but maybe it will get you thinking...
Add this where your comments is:
VB Code:
Me.Visible = False
Me.Visible = True
Maybe its just a matter of setting a property of the mdi form which whill initiate a refresh.
-
Re: scroll MDI Container with mouse wheel???
Quote:
Originally Posted by adamm83
Also, one thing I noticed is it scrolls the child even if it's smaller than the parent. What I mean is, even if there is no vertical scrollbar, it still scrolls the child, which is not necessary.
add this line:
VB Code:
With Me.ActiveForm
[B]If .Top >= 0 And .Height < Me.ScaleHeight Then Exit Sub[/B]
If Rotation > 0 Then
Quote:
Originally Posted by adamm83
I will take a look at the code and see what I can do with it. I will also try out the FreeWheel and/or MS Intellipoint app that westconn1 suggested. I would honestly rather install a small mouse driver to fix the problem rather than add some code that may or may not cause other conflicts with my application.
if you aim to distribute your app then this isn't really an option - if it's just for yourself then getting a new driver would be the easier thing to do.
-
Re: scroll MDI Container with mouse wheel???
ok so I tested out IntelliPoint and FreeWheel and neither of them accomplish what your code can do. Neither of them can scroll the mdi container.
Quote:
Originally Posted by bushmobile
add this line:
VB Code:
With Me.ActiveForm
[B]If .Top >= 0 And .Height < Me.ScaleHeight Then Exit Sub[/B]
If Rotation > 0 Then
if you aim to distribute your app then this isn't really an option - if it's just for yourself then getting a new driver would be the easier thing to do.
Thanks, that fixed the problem. Figured out the refresh yet? I'm sure there is some sort of API or code that will force refresh a form. I will see what else I can do to refresh.
-
Re: scroll MDI Container with mouse wheel???
Quote:
Originally Posted by adamm83
Figured out the refresh yet? I'm sure there is some sort of API or code that will force refresh a form. I will see what else I can do to refresh.
I tried almost everything I could think of and nothing worked. this was the best I could come up with:
VB Code:
' In declarations
Private Declare Function LockWindowUpdate Lib "user32" Alias "LockWindowUpdate" (ByVal hwndLock As Long) As Long
' in the place where we want the refresh
LockWindowUpdate Me.hWnd
Me.Height = Me.Height + 15
Me.Height = Me.Height - 15
LockWindowUpdate False
Since we're changing the size of the window the entire desktop will be redrawn (the icons will flicker like crazy)
-
Re: scroll MDI Container with mouse wheel???
hmmm ... wierd. I tried that before, and it didn't work for me. I'll try it again. what does LockWindowUpdate do?
EDIT:
Ok I tried it out and it works!... I also tried removing the 2 LockWindowUpdate lines and it works as well.... without the icon flickering. So I'm not sure what LockWindowUpdate does, but it seems to work without it.
-
Re: scroll MDI Container with mouse wheel???
-
Re: scroll MDI Container with mouse wheel???
-
1 Attachment(s)
Re: scroll MDI Container with mouse wheel???
if you don't use LockWindowUpdate then you can see the form changing size. here's a working example:
-
Re: scroll MDI Container with mouse wheel???
VB Code:
Public Sub MouseWheel(ByVal MouseKeys As Long, ByVal Rotation As Long, ByVal Xpos As Long, ByVal Ypos As Long)
Dim hwndMDI As Long
Const lScrollAmount As Long = 180
With Me.ActiveForm
If .Top >= 0 And .Height < Me.ScaleHeight Then Exit Sub
If Rotation > 0 Then
If .Top < 0 Then .Top = .Top + lScrollAmount
If .Top > 0 Then .Top = 0
Else
If .Top + .Height > Me.ScaleHeight Then .Top = .Top - lScrollAmount
If .Top + .Height < Me.ScaleHeight Then .Top = Me.ScaleHeight - .Height
End If
End With
hwndMDI = FindWindowEx(Me.hwnd, 0, "MDIClient", vbNullString)
If hwndMDI <> 0 Then
ShowWindow hwndMDI, 0
ShowWindow hwndMDI, 1
End If
End Sub
you need to enforce a MDIClient window update. i used showwindow but other APIs might work as well (movewindow?).
EDIT:
ok, this one doesn't make sense but it works :sick:
VB Code:
Private Declare Function ShowScrollBar Lib "user32" (ByVal hwnd As Long, ByVal wBar As Long, ByVal bShow As Long) As Long
Private Const SB_HORZ = 0
Private Const SB_VERT = 1
Private Const SB_BOTH = 3
...
Public Sub MouseWheel(ByVal MouseKeys As Long, ByVal Rotation As Long, ByVal Xpos As Long, ByVal Ypos As Long)
...
hwndMDI = FindWindowEx(Me.hwnd, 0, "MDIClient", vbNullString)
If hwndMDI <> 0 Then
ShowScrollBar hwndMDI, SB_VERT, False
End If
...
it's supposed to hide the scrollbar but it only gets updated.
-
Re: scroll MDI Container with mouse wheel???
agilaz, where is the declaration for FindWindowEx and ShowScrollbar and the var for hwndMDI??
-
Re: scroll MDI Container with mouse wheel???
@Agilaz: good stuff - i think it became a case of "can't see the wood for the trees" for me.
@adamm83: Look them up at AllAPI.net
-
Re: scroll MDI Container with mouse wheel???
thanks... AllAPI is a nice resource!!!
But what do I declare hwndMDI as?
Dim hwndMDI As ????
-
Re: scroll MDI Container with mouse wheel???
You'll see from the declaration that FindWindowEx returns a Long, so...
-
Re: scroll MDI Container with mouse wheel???
ah :blush: :blush: :blush:
thanks.. have a ducky :duck:
-
Re: scroll MDI Container with mouse wheel???
GREAT! :D I integrated it into my application and it works like a charm!!! :thumb:
Thanks bushmobile AND aliganz!!! I appreciate all the time and help you offered!!!
Quick question though... how do I change the speed it scrolls, or rather the amount it scrolls?
EDIT:
NVM.. figured it out... I didn't open my eyes wide enough :blush:
-
Re: scroll MDI Container with mouse wheel???
No Probs :thumb:
Don't forget to mark this thread resolved using the thread tools just above your first post
-
Re: scroll MDI Container with mouse wheel???
ok problem.
I get an Error 91: Object variable or With block not set when I try to scroll while there is no child in the mdi parent.
I assume this is because it's trying to access the position of a child form which does not exist. How can I avoid this?
-
Re: scroll MDI Container with mouse wheel???
VB Code:
Const lScrollAmount As Long = 180
If Me.ActiveForm Is Nothing Then Exit Sub
With Me.ActiveForm
-
Re: scroll MDI Container with mouse wheel???
perfect! I'm a happy camper!
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
May I suggest a minor mod:-
VB Code:
With Me.ActiveForm
If .Top >= 0 And [COLOR=Red](.Top +[/COLOR] .Height[COLOR=Red])[/COLOR] < Me.ScaleHeight Then Exit Sub
If Rotation > 0 Then
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
crap i thought everything was working, but i notice now that when I exit my app using the close button on the toolbar controls (the x at the top right coner), it seems to crash (without any errors).
What would cause this?? I realize it could be any number of things, but my app is very large. I use the MDIForm's QueryUnload routine when shutting down my app, could this be the problem?
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
what code are you using to close the form?
Are you using End anywhere? If so, don't - use Unload Me
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
I have several forms, not just an mdiform... I unload each manually (unload FormName).
Problem is that once I unload all my forms, there is still something running from my program, so I use End after I unload all my forms. :blush: How can I find out what residue is left behind from my app ??? :confused: so that I don't have to use End...
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
Quote:
Originally Posted by adamm83
I have several forms, not just an mdiform... I unload each manually (unload FormName).
Problem is that once I unload all my forms, there is still something running from my program, so I use End after I unload all my forms. :blush: How can I find out what residue is left behind from my app ??? :confused: so that I don't have to use End...
You probably still have a form that hasn't been unloaded, or something that hasn't been closed, or an object that hasn't been set to nothing... without seeing your project its impossible to say what.
& just to double check - have you definitely got Call WheelUnHook(Me.hwnd) in the MDIForm_Unload event
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
yes I tried placing it in MDIForm_Unload, MDIForm_QueryUnload as well as the my sub routine that unloads all the forms.
My app did not crash when closing until I load/unload the WheelUnHook.
I know this doesn't relate to the topic but is there any way I trace what is left behind? like another program?
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
as soon as you start subclassing doing certain things wrong that your program would have coped with previously can crash your program - without seeing the code it's hard to help you - perhaps upload your project.
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
ahahha not a chance, it's a huge program and would not be worth your time to go through it all. I think I will just try and see what I can do on my own.
Do you know of any third aprty apps that would help debug my code to see whats going on?
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
you should know what you're using and therefore you should know what you need to close/destroy.
I'm not aware of any 3rd party apps - search the forum - you may find some more info.
-
Re: [RESOLVED] scroll MDI Container with mouse wheel???
I do know exactly what I'm using, but its hard to track everything in my app as it is a lot of code. :confused: