我正在使用图像/页面方案进行WinForms应用程序(用户通过单击图像的特定区域在图像之间导航)。在一个页面我创建了富文本框,我想在其中加载“规则”以供用户接受。不幸的是,规则比RTB长,所以我不得不应用某种滚动。我不想让用户使用滚动条 - 而是我制作了两个按钮(向上和向下),用户可以通过这些按钮滑过规则 - 用户无法以任何其他方式选择或移动文本。除了一件事之外,一切都很有效 - 单击按钮后,文本会滑动,但是第一行和最后一行的部分正在被剪切(只有部分高度的线在rtb中可见)。
下面我列出了用于制作此类RTB的代码(名为“规则”):
rules.Clear();
rules.Cursor = Cursors.Default;
rules.ScrollBars = RichTextBoxScrollBars.Vertical;
rules.ReadOnly = true;
rules.KeyPress += rules_KeyPress;
rules.SelectionChanged += rules_SelectionChanged;
rules.Location = new System.Drawing.Point(450*this.Width/2000, 550*this.Height/1125);
Console.WriteLine(rules.Font);
float size = 16.5F;
rules.Font = new Font("Microsoft Sans Serif", size);
Console.WriteLine(rules.Font);
using (Graphics g = rules.CreateGraphics())
{
rules_line_height = Convert.ToInt32(g.MeasureString("A", rules.Font).Height); //getting the measure of the line
Console.WriteLine(rules_line_height);
}
int rules_h = 400 * this.Height / 1125; //height of the rtb
int lines_n = rules_h / rules_line_height; //max number of lines that can be fit in the height
rules.Size = new System.Drawing.Size(1000 * this.Width / 2000, lines_n*rules_line_height); //height of the rtb adjusted to fill full lines
rules.ForeColor = Color.White;
string fileName = "reg_pl.txt";
string line = "";
StreamReader file = new System.IO.StreamReader(Directory.GetCurrentDirectory() + "/reg/" + fileName, Encoding.GetEncoding("windows-1250"));
while ((line = file.ReadLine()) != null)
{
rules.AppendText(line + "\r\n");
}
file.Close();
rules_max = rules.GetMaxRange(); //getting max range of the rtb
rules_thumb = rules.GetThumb(); //getting size of visible part of the rtb
rules_loc = 0; // current location visible part compared to the whole rtb
rules.ScrollBars = RichTextBoxScrollBars.None;
rules.BorderStyle = BorderStyle.None;
rules.BackColor = Color.FromArgb(18, 25, 56);
rules.BringToFront();
我还使用custom_RTB类来获取RTB的最大范围和拇指并滚动到RTB的选定点:
public class CustomRTB : System.Windows.Forms.RichTextBox
{
#region API Stuff
public struct SCROLLINFO
{
public int cbSize;
public int fMask;
public int min;
public int max;
public int nPage;
public int nPos;
public int nTrackPos;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
private static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32")]
private static extern int GetScrollInfo(IntPtr hwnd, int nBar,
ref SCROLLINFO scrollInfo);
private const int SB_HORZ = 0x0;
private const int SB_VERT = 0x1;
#endregion
public int HorizontalPosition
{
get { return GetScrollPos((IntPtr)this.Handle, SB_HORZ); }
set { SetScrollPos((IntPtr)this.Handle, SB_HORZ, value, true); }
}
public int VerticalPosition
{
get { return GetScrollPos((IntPtr)this.Handle, SB_VERT); }
set { SetScrollPos((IntPtr)this.Handle, SB_VERT, value, true); }
}
public void ScrollTo(int Position)
{
SetScrollPos((IntPtr)this.Handle, 0x1, Position, true);
PostMessage((IntPtr)this.Handle, 0x115, 4 + 0x10000 * Position, 0);
}
public int GetMaxRange()
{
SCROLLINFO scrollInfo = new SCROLLINFO();
scrollInfo.cbSize = Marshal.SizeOf(scrollInfo);
//SIF_RANGE = 0x1, SIF_TRACKPOS = 0x10, SIF_PAGE= 0x2
scrollInfo.fMask = 0x10 | 0x1 | 0x2;
GetScrollInfo((IntPtr)this.Handle, 1, ref scrollInfo);//nBar = 1 -> VScrollbar
return scrollInfo.max;
}
public int GetThumb()
{
SCROLLINFO scrollInfo = new SCROLLINFO();
scrollInfo.cbSize = Marshal.SizeOf(scrollInfo);
//SIF_RANGE = 0x1, SIF_TRACKPOS = 0x10, SIF_PAGE= 0x2
scrollInfo.fMask = 0x10 | 0x1 | 0x2;
GetScrollInfo((IntPtr)this.Handle, 1, ref scrollInfo);//nBar = 1 -> VScrollbar
return scrollInfo.nPage;
}
public int GetCurPos()
{
SCROLLINFO scrollInfo = new SCROLLINFO();
scrollInfo.cbSize = Marshal.SizeOf(scrollInfo);
//SIF_RANGE = 0x1, SIF_TRACKPOS = 0x10, SIF_PAGE= 0x2
scrollInfo.fMask = 0x10 | 0x1 | 0x2;
GetScrollInfo((IntPtr)this.Handle, 1, ref scrollInfo);//nBar = 1 -> VScrollbar
return scrollInfo.nTrackPos;
}
public bool ReachedBottom()
{
SCROLLINFO scrollInfo = new SCROLLINFO();
scrollInfo.cbSize = Marshal.SizeOf(scrollInfo);
//SIF_RANGE = 0x1, SIF_TRACKPOS = 0x10, SIF_PAGE= 0x2
scrollInfo.fMask = 0x10 | 0x1 | 0x2;
GetScrollInfo((IntPtr)this.Handle, 1, ref scrollInfo);//nBar = 1 -> VScrollbar
return scrollInfo.max == scrollInfo.nTrackPos + scrollInfo.nPage;
}
}
以下是用于移动文本的“按钮”:
int lines = rules_thumb / rules_line_height; //getting max number of lines that can be visible
int new_thumb = lines * rules_line_height; //getting the move value so the lines won't be cut
if (rules_loc - (new_thumb) >= 0) //if moving by the move value will be still over 0, then proceed normally
{
rules_loc -= (new_thumb);
rules.ScrollTo(rules_loc);
}
else // if it will pass 0, the move to 0
{
rules_loc = 0;
rules.ScrollTo(rules_loc);
}
向下:
int lines = rules_thumb / rules_line_height;
int new_thumb = lines * rules_line_height;
if (rules_loc + (new_thumb) < rules_max)
{
rules_loc += (new_thumb);
rules.ScrollTo(rules_loc);
}
else
{
rules.ScrollTo(rules_max);
}
我认为我做错了的是测量给定字体的线条并设置RTB的良好尺寸。有没有人有类似的问题,能以某种方式协助我吗?
提前感谢您的回答。
祝你好运, Sarachiel