Skip to content

Commit

Permalink
Merge pull request #16 from Xanfre/master
Browse files Browse the repository at this point in the history
Improve RichTextBox reader mode
  • Loading branch information
FenPhoenix authored May 20, 2019
2 parents 99d765c + de73e09 commit 9879026
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 4 deletions.
39 changes: 39 additions & 0 deletions AngelLoader/CustomControls/DataGridViewCustom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,45 @@ internal void FillColumns(List<ColumnData> columnDataList)

#endregion

#region Horizontal scrolling

public const int WM_MOUSEHWHEEL = 0x020E;

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.HWnd != Handle)
{
return;
}
else
{
if (m.Msg == WM_MOUSEHWHEEL)
{
int delta = (int)m.WParam;
if (delta < 0)
{
if (HorizontalScrollingOffset > 14)
{
HorizontalScrollingOffset -= 15;
}
else
{
HorizontalScrollingOffset = 0;
}
m.Result = (IntPtr)1;
}
if (delta > 0)
{
HorizontalScrollingOffset += 15;
m.Result = (IntPtr)1;
}
}
}
}

#endregion

protected override void Dispose(bool disposing)
{
if (disposing)
Expand Down
182 changes: 178 additions & 4 deletions AngelLoader/CustomControls/RichTextBoxCustom.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
Expand Down Expand Up @@ -29,6 +32,14 @@ public RichTextBoxCustom()
// Make sure this is valid right from the start
_scrollInfo.cbSize = (uint)Marshal.SizeOf(_scrollInfo);
_scrollInfo.fMask = (uint)ScrollInfoMask.SIF_ALL;
ReaderModeEnabled = true;
tmrAutoScroll = new Timer();
tmrAutoScroll.Interval = 10;
tmrAutoScroll.Tick += new EventHandler(tmrAutoScroll_Tick);
pbGlyph = new PictureBox();
pbGlyph.Size = new Size(26, 26);
pbGlyph.Visible = false;
Controls.Add(pbGlyph);
}

#region Zoom stuff
Expand Down Expand Up @@ -388,6 +399,149 @@ private void InterceptMousewheel(ref Message m)

#endregion

#region Better reader mode

private class NativeMethods
{
[DllImport("comctl32.dll", SetLastError = true, EntryPoint = "#383")]
public static extern void DoReaderMode(ref InteropTypes.READERMODEINFO prmi);
}

private class InteropTypes
{
public const int WM_MBUTTONDOWN = 0x0207;
public const int WM_MBUTTONUP = 0x0208;
public const int WM_XBUTTONDOWN = 0x020B;
public const int WM_LBUTTONDOWN = 0x0201;
public const int WM_RBUTTONDOWN = 0x0204;
public const int WM_MOUSELEAVE = 0x02A3;
public const int WM_MOUSEWHEEL = 0x020A;
public const int WM_MOUSEHWHEEL = 0x020E;
public const int WM_KEYDOWN = 0x0100;
public delegate bool TranslateDispatchCallbackDelegate(ref Message lpmsg);
public delegate bool ReaderScrollCallbackDelegate(ref READERMODEINFO prmi, int dx, int dy);
[Flags]
public enum ReaderModeFlags
{
None = 0x00,
ZeroCursor = 0x01,
VerticalOnly = 0x02,
HorizontalOnly = 0x04
}

[StructLayout(LayoutKind.Sequential)]
public struct READERMODEINFO
{
public int cbSize;
public IntPtr hwnd;
public ReaderModeFlags fFlags;
public IntPtr prc;
public ReaderScrollCallbackDelegate pfnScroll;
public TranslateDispatchCallbackDelegate fFlags2;
public IntPtr lParam;
}
}

Timer tmrAutoScroll;
int scrollIncrementY;
PictureBox pbGlyph;
bool endOnMouseUp;

[DefaultValue(true), Category("Behavior"), Description("Enables reader mode for the control.")]
public bool ReaderModeEnabled
{
get;
set;
}

void tmrAutoScroll_Tick(object sender, EventArgs e)
{
//Scroll RichTextBox using pixels rather than lines
BetterScroll(Handle, scrollIncrementY);
}

private bool TranslateDispatchCallback(ref Message msg)
{
bool isMouseDown = false;
switch (msg.Msg)
{
case InteropTypes.WM_LBUTTONDOWN:
case InteropTypes.WM_MBUTTONDOWN:
case InteropTypes.WM_RBUTTONDOWN:
case InteropTypes.WM_XBUTTONDOWN:
case InteropTypes.WM_MOUSEWHEEL:
case InteropTypes.WM_MOUSEHWHEEL:
case InteropTypes.WM_KEYDOWN:
isMouseDown = true;
break;
}

if (isMouseDown || (endOnMouseUp && (msg.Msg == InteropTypes.WM_MBUTTONUP)))
{
// exit reader mode
tmrAutoScroll.Stop();
}

if ((!endOnMouseUp && (msg.Msg == InteropTypes.WM_MBUTTONUP)) || (msg.Msg == InteropTypes.WM_MOUSELEAVE))
{
return true;
}

if (isMouseDown)
{
msg.Msg = InteropTypes.WM_MBUTTONDOWN;
}

return false;
}

private bool ReaderScrollCallback(ref InteropTypes.READERMODEINFO prmi, int dx, int dy)
{
scrollIncrementY = dy;

if (dy != 0) endOnMouseUp = true;

return true;
}

private InteropTypes.ReaderModeFlags GetReaderModeFlags()
{
return InteropTypes.ReaderModeFlags.VerticalOnly;
}

private void EnterReaderMode()
{
// bounds to get the scrolling sensitivity
Rectangle scrollBounds = new Rectangle(pbGlyph.Left, pbGlyph.Top, pbGlyph.Right, pbGlyph.Bottom);
IntPtr rectPtr = Marshal.AllocHGlobal(Marshal.SizeOf(scrollBounds));

try
{
Marshal.StructureToPtr(scrollBounds, rectPtr, true);

InteropTypes.READERMODEINFO readerInfo = new InteropTypes.READERMODEINFO
{
hwnd = Handle,
fFlags = GetReaderModeFlags(),
prc = rectPtr,
lParam = IntPtr.Zero,
fFlags2 = new InteropTypes.TranslateDispatchCallbackDelegate(TranslateDispatchCallback),
pfnScroll = new InteropTypes.ReaderScrollCallbackDelegate(ReaderScrollCallback)
};

readerInfo.cbSize = Marshal.SizeOf(readerInfo);

// enable reader mode
NativeMethods.DoReaderMode(ref readerInfo);
}
finally
{
Marshal.FreeHGlobal(rectPtr);
}
}

#endregion

[DllImport("user32.dll")]
public static extern IntPtr SetCursor(HandleRef hcursor);

Expand Down Expand Up @@ -430,13 +584,23 @@ protected override void WndProc(ref Message m)
case InteropMisc.WM_MOUSEWHEEL:
InterceptMousewheel(ref m);
break;
// Fix the flickering that is present when reader mode is entered
// Intercept the middle mouse button and direct it to use the fixed reader mode
case InteropMisc.WM_MBUTTONDOWN:
case InteropMisc.WM_MBUTTONUP:
case InteropMisc.WM_MBUTTONDBLCLK:
SetStyle(ControlStyles.Selectable, false);
DefWndProc(ref m);
SetStyle(ControlStyles.Selectable, true);
if ((ReaderModeEnabled))
{
if (VerticalScrollBarVisible(this))
{
// Enter reader mode
pbGlyph.Location = Point.Subtract(this.PointToClient(Control.MousePosition), new Size(13, 13));
SetCursor(new HandleRef(Cursors.NoMoveVert, Cursors.NoMoveVert.Handle));
m.Result = (IntPtr)1;
tmrAutoScroll.Start();
endOnMouseUp = false;
EnterReaderMode();
}
}
break;
// The below DefWndProc() call essentially "calls" this section, and this section "returns" whether
// the cursor was over a link (via LinkCursor)
Expand Down Expand Up @@ -798,5 +962,15 @@ private static string GLMLToRTF(string text)
}

#endregion

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (tmrAutoScroll != null) tmrAutoScroll.Dispose();
if (pbGlyph != null) pbGlyph.Dispose();
}
base.Dispose(disposing);
}
}
}

0 comments on commit 9879026

Please sign in to comment.