If anyone else is trying to to this, I came accross this excellent article..
http://www.codeproject.com/csharp/Md...asp#xx948448xx
which used Native methods..
The code below seems to let me track what the heck is happening in the
MdiClient window...There is some use of internal Win32 routines for accessing
and handling Windows Messages so you would have to change these but it will
give you an idea as I have spent far too much time on this...
//To use this
MdiClientNativeWindow mdiClientNative = new MdiClientNativeWindow(this);
mdiClientNative.Scrolled
+=new EventHandler(MdiClient_Scrolled);
mdiClientNative.MdiWindowPositionChanged
+=new EventHandler(MdiClientNative_MdiWindowPositionChanged);
//***************** MdiClientNativeWindow *****************
using System;
using System.Windows.Forms;
using System.Diagnostics;
using Bon.Win32;
namespace Bon.Forms
{
/// <summary>
/// Class: Provide access to an MdiClient in a MdiForm MdiClientNativeWindow.
/// </summary>
public class MdiClientNativeWindow: System.Windows.Forms.NativeWindow
{
/// <summary>
/// Field: is MdiClient Vertical Scroll bar active
/// </summary>
private bool verticalScrollActive;
/// <summary>
/// Property: Gets if MdiClient Window is Scrolling Vertically
/// </summary>
public bool VerticalScrollActive
{
[DebuggerStepThrough()]
get { return verticalScrollActive;}
}
/// <summary>
/// Field: is MdiClient Horizontal Scroll bar active
/// </summary>
private bool horizontalScrollActive;
/// <summary>
/// Property: Gets if MdiClient Window is Scrolling Horizontally
/// </summary>
public bool HorizontalScrollActive
{
[DebuggerStepThrough()]
get { return horizontalScrollActive;}
}
private Form parentForm;
/// <summary>
/// Property: Gets the Parent Form
/// </summary>
public Form ParentForm
{
[DebuggerStepThrough()]
get { return parentForm;}
}
private MdiClient mdiClient;
/// <summary>
/// Property: Gets the MdiClient
/// </summary>
public MdiClient MdiClient
{
[DebuggerStepThrough()]
get { return mdiClient;}
}
/// <summary>
/// Event: MdiClient Window Position Changed (recieved WM_WINDOWPOSCHANGED)
/// </summary>
public event System.EventHandler MdiWindowPositionChanged;
/// <summary>
/// Event: MdiClient Set Cursor message (recieved WM_SETCURSOR)
/// </summary>
public event System.EventHandler MdiSetCursor;
/// <summary>
/// Event: MdiClient Window Activated (recieved WM_MDIGETACTIVE)
/// </summary>
public event System.EventHandler MdiGetActive;
/// <summary>
/// Event: MdiClient Window is About to Start Scrolling
/// </summary>
public event System.EventHandler ScrollingStarted;
/// <summary>
/// Event: MdiClient Window is Scrolling
/// </summary>
public event System.Windows.Forms.ScrollEventHandler Scrolling;
/// <summary>
/// Event: MdiClient Window has scrolled
/// </summary>
public event System.EventHandler Scrolled;
/// <summary>
/// Constructor: Default
/// </summary>
public MdiClientNativeWindow():this(null)
{
}
/// <summary>
/// Constructor: with Parent Form
/// </summary>
/// <param name="parentForm"></param>
public MdiClientNativeWindow(Form parentForm)
{
this.verticalScrollActive = false;
this.horizontalScrollActive = false;
this.mdiClient = null;
this.parentForm = parentForm;
InitializeMdiClient();
}
protected override void WndProc(ref Message m)
{
try
{
WM msg = Win32API.Get_WM (m);
Debug.WriteLine("MdiClientNativeWindow->"+msg.ToString() );
switch (msg)
{
//This will check if scrolling Started
case WM.WM_NCLBUTTONDOWN:
MouseLeftClickNonClient(ref m);
break;
//Scolling progress and Completion will be triggered
case WM.WM_VSCROLL:
case WM.WM_HSCROLL:
TriggerScrolling(ref m);
break;
//Consume this event to stop background Painting
case WM.WM_ERASEBKGND:
return;
case WM.WM_SYNCPAINT:
case WM.WM_PAINT:
case WM.WM_MOVE:
break;
//Need to Trap this event So Background can be refreshed
case WM.WM_MDIGETACTIVE:
TriggerMdiGetActive();
break;
case WM.WM_SETCURSOR:
TriggerMdiSetCursor();
break;
case WM.WM_WINDOWPOSCHANGED:
TriggerMdiWindowPositionChanged();
break;
}
}
catch
{
}
base.WndProc (ref m);
}
private void MouseLeftClickNonClient(ref Message m)
{
//Is Scroll Active
if ( m.WParam == (IntPtr)HT.HTVSCROLL )
{
VerticalScrollActivated();
}
else if ( m.WParam == (IntPtr)HT.HTVSCROLL )
{
HorizontalScrollActivated();
}
}
private void HorizontalScrollActivated()
{
horizontalScrollActive = true;
TriggerScrollingStarted();
}
private void VerticalScrollActivated()
{
verticalScrollActive = true;
TriggerScrollingStarted();
}
private void TriggerMdiWindowPositionChanged()
{
if (MdiWindowPositionChanged != null)
{
MdiWindowPositionChanged(this,new EventArgs() );
}
}
private void TriggerMdiSetCursor()
{
if (MdiSetCursor != null)
{
MdiSetCursor(this,new EventArgs() );
}
}
private void TriggerMdiGetActive()
{
if (MdiGetActive != null)
{
MdiGetActive(this,new EventArgs() );
}
}
private void TriggerScrollingStarted()
{
if (ScrollingStarted != null)
{
ScrollingStarted(this,new EventArgs() );
}
}
private void TriggerScrolled()
{
if (Scrolled != null)
{
Scrolled(this,new EventArgs() );
}
} /// <summary>
/// Method: Triggers a Scroll Event and Monitors the Scroll requests
/// looking for a SB_ThumbPostions so that
/// a Scrolled message can be sent
/// </summary>
/// <param name="m"></param>
private void TriggerScrolling(ref Message m)
{
//Monitor
//
//wParam The high-order word specifies the current position
// of the scroll box if the low-order word
// is SB_THUMBPOSITION or SB_THUMBTRACK;
// otherwise, this word is not used.
//
//The low-order word specifies a scroll bar value that
//indicates the user's scrolling request.
//
//This parameter can be one of the following values.
//
//SB_BOTTOM - Scrolls to the lower right.
//SB_ENDSCROLL - Ends scroll.
//SB_LINEDOWN - Scrolls one line down.
//SB_LINEUP - Scrolls one line up.
//SB_PAGEDOWN - Scrolls one page down.
//SB_PAGEUP - Scrolls one page up.
//SB_THUMBPOSITION - The user has dragged the scroll box (thumb)
// and released the mouse button.
// The high-order word indicates
// the position of the scroll box at the end of the drag operation.
//SB_THUMBTRACK - The user is dragging the scroll box.
// This message is sent repeatedly until
// the user releases the mouse button.
// The high-order word indicates the position
// that the scroll box has been dragged to.
// SB_TOP
// Scrolls to the upper left.
//lParam
//------
//If the message is sent by a scroll bar,
//this parameter is the handle to the scroll bar control.
//If the message is not sent by a scroll bar,
//this parameter is NULL.
//
ScrollEventArgs scrollArgs = ScrollArgsFromMessage(ref m);
//Scroll Event
if (this.Scrolling != null)
{
Scrolling(this.mdiClient,scrollArgs);
}
//This means the Scroll Bar has moved so Fired Completed Event
if (scrollArgs.Type == ScrollEventType.ThumbPosition)
{
//Indicated Scolled before resetting flags..
if (Scrolled != null)
{
Scrolled(mdiClient,new EventArgs() );
}
verticalScrollActive = false;
horizontalScrollActive = false;
}
}
/// <summary>
/// Method: Create a Scroll Argument from a Windows Message
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
private ScrollEventArgs ScrollArgsFromMessage(ref Message m)
{
//Scroll Button Enmeration...
SB sb = (SB)Win32API.WParam_LoWord(m);
ScrollEventType scrollType = (ScrollEventType)sb;
//Position
int scrollPosition = Win32API.WParam_HiWord(m);
return new ScrollEventArgs(scrollType,scrollPosition);
}
private void InitializeMdiClient()
{
// If the mdiClient has previously been set, unwire events connected
// to the old MDI.
if(mdiClient != null)
mdiClient.HandleDestroyed -= new EventHandler(MdiClientHandleDestroyed);
if(parentForm == null)
{
return;
}
// Get the MdiClient from the parent form.
for(int i = 0; i < parentForm.Controls.Count; i++)
{
// If the form is an MDI container, it will contain an MdiClient control
// just as it would any other control.
mdiClient = parentForm.Controls[i] as MdiClient;
if(mdiClient != null)
{
// Assign the MdiClient Handle to the NativeWindow.
ReleaseHandle();
AssignHandle(mdiClient.Handle);
// Raise the HandleAssigned event.
//OnHandleAssigned(EventArgs.Empty);
// Monitor the MdiClient for when its handle is destroyed.
mdiClient.HandleDestroyed += new EventHandler(MdiClientHandleDestroyed);
}
}
}
/// <summary>
/// Method: MdiClient handle has been released, so drop the reference and
/// release the handle.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MdiClientHandleDestroyed(object sender, EventArgs e)
{
if(mdiClient != null)
{
mdiClient.HandleDestroyed -= new EventHandler(MdiClientHandleDestroyed);
mdiClient = null;
}
ReleaseHandle();
}
}
}