Recently I'm on a form project with custom GUI. (MetroFrameWork) It has its own TextBox component, but I prefer RichTextBox. The problem is that it uses the windows legacy scrollbar if I set it visible. I don't want to use this. Luckily framework has its own ScrollBar component with skin I want. I can set RichTextBox with NO scrollbar (ScrollBars property set to NONE) and set the independent custom scrollbar docked to right to RichTextBox. I didn't find any good solution how could I derive or attach custom scrollbar control to my legacy RichTextBox as if it behaviors as RTB's built in scrollbar. So I tried to do it manually. When populate RTB, I can calculate my custom scrollbar Minimum, Maximum, SmallChange, LargeChange properties so it can set scrollbar thumb size. I achieved to emulate the scrolling method with cathich custom scrollbar's scroll event then could scroll RTB's text content vertically (only need vertical scroll) with interop services (user32.dll):
private void metroScrollBarRichTextBoxMain_Scroll(object sender, ScrollEventArgs e)
{
uint nPos = (uint)metroScrollBarRichTextBoxMain.Value * (uint)Math.Round((decimal)richTextBoxMain.Font.GetHeight(), 1, MidpointRounding.AwayFromZero);
uint wParam = (uint)WindowMessageConstants.ScrollBarCommands.SB_THUMBPOSITION | nPos << 16;
SendMessage(richTextBoxMain.Handle, WindowMessageConstants.WM_VSCROLL, (IntPtr)wParam, IntPtr.Zero);
}
So scrolling with mouse while we hold the scrollbar's thumb is ok. But here is the catch, I wanna use RichTextBox other abilites such as scroll text content with arrow keys and mousewheel. Mousewheel is ok, it could be implemented easily. But I can't find any solution to catch event if user scroll the content with keyboard arrows. It needed because I have to sync position to my custom scrollbar. I didn't find any solution what's happening when RTB move the text content one line down or up when you use keyboard arrows. Nor when you make your selection with mouse and slide towards the upper or lower edge of RTB (it will scroll the text too) What event fires in this case? It is like ScrollToCaret function, but it doesn't fire any event. Other approach if I set vertical scrollbar visible, and "hide" behind my custom scrollbar. In this case I could get scroll position to sync my scrollbar pos. But this is ugly, there must be a better way. I tried to capture if any scroll effect happening via WndProc:
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WindowMessageConstants.WM_VSCROLL || m.Msg == WindowMessageConstants.WM_HSCROLL ||
m.Msg == WindowMessageConstants.WM_MOUSEWHEEL)
{
...do something here
}
}
But this is only when scroll or mousewheel scroll happening. Not when you scroll WITH keyboard arrows.
Can you guys show me a way how could I achieve this? Or maybe my approach is completely wrong, maybe there is way, I could derive/inherit legacy RTB controls to/from my custom scrollbar's controls so I can completely attach the custom scrollbar to richtextbox WHILE RTB's ScrollBars property set to NONE. (so built in scrollbars not visible)
Sorry for my long explanation, I searched solution everywhere with no success for days...