SyntaxHighlighter part2

    技术2022-05-11  46

    using System;using System.Collections;using System.ComponentModel;using System.Drawing;using System.Data;using System.Windows.Forms;using System.Text;using System.Runtime.InteropServices;

    namespace UrielGuy.SyntaxHighlightingTextBox{ /// <summary> /// A textbox the does syntax highlighting. /// </summary> public class SyntaxHighlightingTextBox : System.Windows.Forms.RichTextBox  {  #region Members

      //Members exposed via properties  private SeperaratorCollection mSeperators = new SeperaratorCollection();    private HighLightDescriptorCollection mHighlightDescriptors = new HighLightDescriptorCollection();  private bool mCaseSesitive = false;  private bool mFilterAutoComplete = false;

      //Internal use members  private bool mAutoCompleteShown = false;  private bool mParsing = false;  private bool mIgnoreLostFocus = false;

      private AutoCompleteForm mAutoCompleteForm = new AutoCompleteForm();

      //Undo/Redo members  private ArrayList mUndoList = new ArrayList();  private Stack mRedoStack = new Stack();  private bool mIsUndo = false;  private UndoRedoInfo mLastInfo = new UndoRedoInfo("", new Win32.POINT(), 0);  private int mMaxUndoRedoSteps = 50;

      #endregion

      #region Properties  /// <summary>  /// Determines if token recognition is case sensitive.  /// </summary>  [Category("Behavior")]  public bool CaseSensitive   {    get    {     return mCaseSesitive;    }   set    {     mCaseSesitive = value;   }  }

      /// <summary>  /// Sets whether or not to remove items from the Autocomplete window as the user types...  /// </summary>  [Category("Behavior")]  public bool FilterAutoComplete   {   get    {    return mFilterAutoComplete;   }   set    {    mFilterAutoComplete = value;   }  }

      /// <summary>  /// Set the maximum amount of Undo/Redo steps.  /// </summary>  [Category("Behavior")]  public int MaxUndoRedoSteps   {   get    {    return mMaxUndoRedoSteps;   }   set   {    mMaxUndoRedoSteps = value;   }  }

       /// <summary>   /// A collection of charecters. a token is every string between two seperators.   /// </summary>   ///    public SeperaratorCollection Seperators   {   get    {    return mSeperators;   }  }    /// <summary>  /// The collection of highlight descriptors.  /// </summary>  ///   public HighLightDescriptorCollection HighlightDescriptors   {   get    {    return mHighlightDescriptors;   }  }

      #endregion

      #region Overriden methods

      /// <summary>  /// The on text changed overrided. Here we parse the text into RTF for the highlighting.  /// </summary>  /// <param name="e"></param>  protected override void OnTextChanged(EventArgs e)  {   if (mParsing) return;   mParsing = true;   Win32.LockWindowUpdate(Handle);   base.OnTextChanged(e);

       if (!mIsUndo)   {    mRedoStack.Clear();    mUndoList.Insert(0,mLastInfo);    this.LimitUndo();    mLastInfo = new UndoRedoInfo(Text, GetScrollPos(), SelectionStart);   }      //Save scroll bar an cursor position, changeing the RTF moves the cursor and scrollbars to top positin   Win32.POINT scrollPos = GetScrollPos();   int cursorLoc = SelectionStart;

       //Created with an estimate of how big the stringbuilder has to be...   StringBuilder sb = new    StringBuilder((int)(Text.Length * 1.5 + 150));    //Adding RTF header   sb.Append(@"{/rtf1/fbidis/ansi/ansicpg1255/deff0/deflang1037{/fonttbl{");      //Font table creation   int fontCounter = 0;   Hashtable fonts = new Hashtable();   AddFontToTable(sb, Font, ref fontCounter, fonts);   foreach (HighlightDescriptor hd in mHighlightDescriptors)   {    if ((hd.Font !=  null) && !fonts.ContainsKey(hd.Font.Name))    {     AddFontToTable(sb, hd.Font,ref fontCounter, fonts);    }   }   sb.Append("}/n");

       //ColorTable      sb.Append(@"{/colortbl ;");   Hashtable colors = new Hashtable();   int colorCounter = 1;   AddColorToTable(sb, ForeColor, ref colorCounter, colors);   AddColorToTable(sb, BackColor, ref colorCounter, colors);      foreach (HighlightDescriptor hd in mHighlightDescriptors)   {    if (!colors.ContainsKey(hd.Color))    {     AddColorToTable(sb, hd.Color, ref colorCounter, colors);    }   }  

       //Parsing text    sb.Append("}/n").Append(@"/viewkind4/uc1/pard/ltrpar");   SetDefaultSettings(sb, colors, fonts);

       char[] sperators = mSeperators.GetAsCharArray();

       //Replacing "/" to "//" for RTF...   string[] lines = Text.Replace("//","").Replace("{", "//{").Replace("}", "//}").Split('/n');   for (int lineCounter = 0 ; lineCounter < lines.Length; lineCounter++)   {    if (lineCounter != 0)    {     AddNewLine(sb);    }    string line = lines[lineCounter];    string[] tokens = mCaseSesitive ? line.Split(sperators) : line.ToUpper().Split(sperators);    if (tokens.Length == 0)    {     sb.Append(line);     AddNewLine(sb);     continue;    }

        int tokenCounter = 0;    for (int i = 0; i < line.Length ;)    {     char curChar = line[i];     if (mSeperators.Contains(curChar))     {      sb.Append(curChar);      i++;     }     else     {      string curToken = tokens[tokenCounter++];      bool bAddToken = true;      foreach (HighlightDescriptor hd in mHighlightDescriptors)      {       string compareStr = mCaseSesitive ? hd.Token : hd.Token.ToUpper();       bool match = false;

           //Check if the highlight descriptor matches the current toker according to the DescriptoRecognision property.       switch (hd.DescriptorRecognition)       {        case DescriptorRecognition.WholeWord:         if (curToken == compareStr)         {           match = true;         }         break;        case DescriptorRecognition.StartsWith:         if (curToken.StartsWith(compareStr))         {          match = true;         }         break;        case DescriptorRecognition.Contains:         if (curToken.IndexOf(compareStr) != -1)         {          match = true;         }         break;       }       if (!match)       {        //If this token doesn't match chech the next one.        continue;       }

           //printing this token will be handled by the inner code, don't apply default settings...       bAddToken = false;        //Set colors to current descriptor settings.       SetDescriptorSettings(sb, hd, colors, fonts);

           //Print text affected by this descriptor.       switch (hd.DescriptorType)       {        case DescriptorType.Word:         sb.Append(line.Substring(i, curToken.Length));         SetDefaultSettings(sb, colors, fonts);         i += curToken.Length;         break;        case DescriptorType.ToEOL:         sb.Append(line.Remove(0, i));         i = line.Length;         SetDefaultSettings(sb, colors, fonts);         break;        case DescriptorType.ToCloseToken:         while((line.IndexOf(hd.CloseToken, i) == -1) && (lineCounter < lines.Length))         {          sb.Append(line.Remove(0, i));          lineCounter++;          if (lineCounter < lines.Length)          {           AddNewLine(sb);           line = lines[lineCounter];           i = 0;          }          else          {           i = line.Length;          }         }         if (line.IndexOf(hd.CloseToken, i) != -1)         {          sb.Append(line.Substring(i, line.IndexOf(hd.CloseToken, i) + hd.CloseToken.Length - i) );          line = line.Remove(0, line.IndexOf(hd.CloseToken, i) + hd.CloseToken.Length);          tokenCounter = 0;          tokens = mCaseSesitive ? line.Split(sperators) : line.ToUpper().Split(sperators);          SetDefaultSettings(sb, colors, fonts);          i = 0;         }         break;       }       break;      }      if (bAddToken)      {       //Print text with default settings...       sb.Append(line.Substring(i, curToken.Length));       i+= curToken.Length;      }     }    }   } //   System.Diagnostics.Debug.WriteLine(sb.ToString());   Rtf = sb.ToString();

       //Restore cursor and scrollbars location.   SelectionStart = cursorLoc;

       mParsing = false;     SetScrollPos(scrollPos);   Win32.LockWindowUpdate((IntPtr)0);   Invalidate();      if (mAutoCompleteShown)   {    if (mFilterAutoComplete)    {     SetAutoCompleteItems();     SetAutoCompleteSize();     SetAutoCompleteLocation(false);    }    SetBestSelectedAutoCompleteItem();   }

      }

      protected override void OnVScroll(EventArgs e)  {   if (mParsing) return;   base.OnVScroll (e);  }

      protected override void OnMouseDown(MouseEventArgs e)  {   HideAutoCompleteForm();   base.OnMouseDown (e);  }

      /// <summary>  /// Taking care of Keyboard events  /// </summary>  /// <param name="m"></param>  /// <remarks>  /// Since even when overriding the OnKeyDown methoed and not calling the base function   /// you don't have full control of the input, I've decided to catch windows messages to handle them.  /// </remarks>  protected override void WndProc(ref Message m)  {   switch (m.Msg)   {    case Win32.WM_PAINT:    {     //Don't draw the control while parsing to avoid flicker.     if (mParsing)     {      return;     }     break;    }    case Win32.WM_KEYDOWN:    {     if (mAutoCompleteShown)     {      switch ((Keys)(int)m.WParam)      {       case Keys.Down:       {        if (mAutoCompleteForm.Items.Count != 0)        {         mAutoCompleteForm.SelectedIndex = (mAutoCompleteForm.SelectedIndex + 1) % mAutoCompleteForm.Items.Count;        }        return;       }       case Keys.Up:       {        if (mAutoCompleteForm.Items.Count != 0)        {         if (mAutoCompleteForm.SelectedIndex < 1)         {          mAutoCompleteForm.SelectedIndex = mAutoCompleteForm.Items.Count - 1;         }         else         {          mAutoCompleteForm.SelectedIndex--;         }        }        return;       }       case Keys.Enter:       case Keys.Space:       {        AcceptAutoCompleteItem();        return;       }       case Keys.Escape:       {        HideAutoCompleteForm();        return;       }              }     }     else     {      if (((Keys)(int)m.WParam == Keys.Space) &&        ((Win32.GetKeyState(Win32.VK_CONTROL) & Win32.KS_KEYDOWN) != 0))      {       CompleteWord();      }       else if (((Keys)(int)m.WParam == Keys.Z) &&        ((Win32.GetKeyState(Win32.VK_CONTROL) & Win32.KS_KEYDOWN) != 0))      {       Undo();       return;      }      else if (((Keys)(int)m.WParam == Keys.Y) &&        ((Win32.GetKeyState(Win32.VK_CONTROL) & Win32.KS_KEYDOWN) != 0))      {       Redo();       return;      }     }     break;    }    case Win32.WM_CHAR:    {     switch ((Keys)(int)m.WParam)     {      case Keys.Space:       if ((Win32.GetKeyState(Win32.VK_CONTROL) & Win32.KS_KEYDOWN )!= 0)       {        return;       }       break;      case Keys.Enter:       if (mAutoCompleteShown) return;       break;     }    }    break;

       }   base.WndProc (ref m);  }

      /// <summary>  /// Hides the AutoComplete form when losing focus on textbox.  /// </summary>  /// <param name="e"></param>  protected override void OnLostFocus(EventArgs e)  {   if (!mIgnoreLostFocus)   {    HideAutoCompleteForm();   }   base.OnLostFocus (e);  }

      #endregion

      #region Undo/Redo Code  public new bool CanUndo   {   get    {    return mUndoList.Count > 0;   }  }  public new bool CanRedo  {   get    {    return mRedoStack.Count > 0;   }  }

      private void LimitUndo()  {   while (mUndoList.Count > mMaxUndoRedoSteps)   {    mUndoList.RemoveAt(mMaxUndoRedoSteps);   }  }

      public new void Undo()  {   if (!CanUndo)    return;   mIsUndo = true;   mRedoStack.Push(new UndoRedoInfo(Text, GetScrollPos(), SelectionStart));   UndoRedoInfo info = (UndoRedoInfo)mUndoList[0];   mUndoList.RemoveAt(0);   Text = info.Text;   SelectionStart = info.CursorLocation;   SetScrollPos(info.ScrollPos);   mLastInfo = info;   mIsUndo = false;  }  public new void Redo()  {   if (!CanRedo)    return;   mIsUndo = true;   mUndoList.Insert(0,new UndoRedoInfo(Text, GetScrollPos(), SelectionStart));   LimitUndo();   UndoRedoInfo info = (UndoRedoInfo)mRedoStack.Pop();   Text = info.Text;   SelectionStart = info.CursorLocation;   SetScrollPos(info.ScrollPos);   mIsUndo = false;  }

      private class UndoRedoInfo  {   public UndoRedoInfo(string text, Win32.POINT scrollPos, int cursorLoc)   {    Text = text;    ScrollPos = scrollPos;    CursorLocation = cursorLoc;   }   public readonly Win32.POINT ScrollPos;   public readonly int CursorLocation;   public readonly string Text;  }  #endregion

      #region AutoComplete functions

      /// <summary>  /// Entry point to autocomplete mechanism.  /// Tries to complete the current word. if it fails it shows the AutoComplete form.  /// </summary>  private void CompleteWord()  {   int curTokenStartIndex = Text.LastIndexOfAny(mSeperators.GetAsCharArray(), Math.Min(SelectionStart, Text.Length - 1))+1;   int curTokenEndIndex= Text.IndexOfAny(mSeperators.GetAsCharArray(), SelectionStart);   if (curTokenEndIndex == -1)    {    curTokenEndIndex = Text.Length;   }   string curTokenString = Text.Substring(curTokenStartIndex, Math.Max(curTokenEndIndex - curTokenStartIndex,0)).ToUpper();      string token = null;   foreach (HighlightDescriptor hd in mHighlightDescriptors)   {    if (hd.UseForAutoComplete && hd.Token.ToUpper().StartsWith(curTokenString))    {     if (token == null)     {      token = hd.Token;     }     else     {      token = null;      break;     }    }   }   if (token == null)   {    ShowAutoComplete();   }   else   {    SelectionStart = curTokenStartIndex;    SelectionLength = curTokenEndIndex - curTokenStartIndex;    SelectedText = token;    SelectionStart = SelectionStart + SelectionLength;    SelectionLength = 0;   }  }

      /// <summary>  /// replace the current word of the cursor with the one from the AutoComplete form and closes it.  /// </summary>  /// <returns>If the operation was succesful</returns>  private bool AcceptAutoCompleteItem()  {      if (mAutoCompleteForm.SelectedItem == null)   {    return false;   }      int curTokenStartIndex = Text.LastIndexOfAny(mSeperators.GetAsCharArray(), Math.Min(SelectionStart, Text.Length - 1)) + 1;   int curTokenEndIndex= Text.IndexOfAny(mSeperators.GetAsCharArray(), SelectionStart);   if (curTokenEndIndex == -1)    {    curTokenEndIndex = Text.Length;   }   SelectionStart = Math.Max(curTokenStartIndex, 0);   SelectionLength = Math.Max(0,curTokenEndIndex - curTokenStartIndex);   SelectedText = mAutoCompleteForm.SelectedItem;   SelectionStart = SelectionStart + SelectionLength;   SelectionLength = 0;      HideAutoCompleteForm();   return true;  }

     

      /// <summary>  /// Finds the and sets the best matching token as the selected item in the AutoCompleteForm.  /// </summary>  private void SetBestSelectedAutoCompleteItem()  {   int curTokenStartIndex = Text.LastIndexOfAny(mSeperators.GetAsCharArray(), Math.Min(SelectionStart, Text.Length - 1))+1;   int curTokenEndIndex= Text.IndexOfAny(mSeperators.GetAsCharArray(), SelectionStart);   if (curTokenEndIndex == -1)    {    curTokenEndIndex = Text.Length;   }   string curTokenString = Text.Substring(curTokenStartIndex, Math.Max(curTokenEndIndex - curTokenStartIndex,0)).ToUpper();      if ((mAutoCompleteForm.SelectedItem != null) &&     mAutoCompleteForm.SelectedItem.ToUpper().StartsWith(curTokenString))   {    return;   }

       int matchingChars = -1;   string bestMatchingToken = null;

       foreach (string item in mAutoCompleteForm.Items)   {    bool isWholeItemMatching = true;    for (int i = 0 ; i < Math.Min(item.Length, curTokenString.Length); i++)    {     if (char.ToUpper(item[i]) != char.ToUpper(curTokenString[i]))     {      isWholeItemMatching = false;      if (i-1 > matchingChars)      {       matchingChars = i;       bestMatchingToken = item;       break;      }     }    }    if (isWholeItemMatching &&     (Math.Min(item.Length, curTokenString.Length) > matchingChars))    {     matchingChars = Math.Min(item.Length, curTokenString.Length);     bestMatchingToken = item;    }   }      if (bestMatchingToken != null)   {    mAutoCompleteForm.SelectedIndex = mAutoCompleteForm.Items.IndexOf(bestMatchingToken);   }

      }

      /// <summary>  /// Sets the items for the AutoComplete form.  /// </summary>  private void SetAutoCompleteItems()  {   mAutoCompleteForm.Items.Clear();   string filterString = "";   if (mFilterAutoComplete)   {       int filterTokenStartIndex = Text.LastIndexOfAny(mSeperators.GetAsCharArray(), Math.Min(SelectionStart, Text.Length - 1))+1;    int filterTokenEndIndex= Text.IndexOfAny(mSeperators.GetAsCharArray(), SelectionStart);    if (filterTokenEndIndex == -1)     {     filterTokenEndIndex = Text.Length;    }    filterString = Text.Substring(filterTokenStartIndex, filterTokenEndIndex - filterTokenStartIndex).ToUpper();   }     foreach (HighlightDescriptor hd in mHighlightDescriptors)   {    if (hd.Token.ToUpper().StartsWith(filterString) && hd.UseForAutoComplete)    {     mAutoCompleteForm.Items.Add(hd.Token);    }   }   mAutoCompleteForm.UpdateView();  }    /// <summary>  /// Sets the size. the size is limited by the MaxSize property in the form itself.  /// </summary>  private void SetAutoCompleteSize()  {   mAutoCompleteForm.Height = Math.Min(    Math.Max(mAutoCompleteForm.Items.Count, 1) * mAutoCompleteForm.ItemHeight + 4,     mAutoCompleteForm.MaximumSize.Height);  }

      /// <summary>  /// closes the AutoCompleteForm.  /// </summary>  private void HideAutoCompleteForm()  {   mAutoCompleteForm.Visible = false;   mAutoCompleteShown = false;  }  

      /// <summary>  /// Sets the location of the AutoComplete form, maiking sure it's on the screen where the cursor is.  /// </summary>  /// <param name="moveHorizontly">determines wheather or not to move the form horizontly.</param>  private void SetAutoCompleteLocation(bool moveHorizontly)  {   Point cursorLocation = GetPositionFromCharIndex(SelectionStart);   Screen screen = Screen.FromPoint(cursorLocation);   Point optimalLocation = new Point(PointToScreen(cursorLocation).X-15, (int)(PointToScreen(cursorLocation).Y + Font.Size*2 + 2));   Rectangle desiredPlace = new Rectangle(optimalLocation , mAutoCompleteForm.Size);   desiredPlace.Width = 152;   if (desiredPlace.Left < screen.Bounds.Left)    {    desiredPlace.X = screen.Bounds.Left;   }   if (desiredPlace.Right > screen.Bounds.Right)   {    desiredPlace.X -= (desiredPlace.Right - screen.Bounds.Right);   }   if (desiredPlace.Bottom > screen.Bounds.Bottom)   {    desiredPlace.Y = cursorLocation.Y - 2 - desiredPlace.Height;   }   if (!moveHorizontly)   {    desiredPlace.X = mAutoCompleteForm.Left;   }

       mAutoCompleteForm.Bounds = desiredPlace;  }

      /// <summary>  /// Shows the Autocomplete form.  /// </summary>  public void ShowAutoComplete()  {   SetAutoCompleteItems();   SetAutoCompleteSize();   SetAutoCompleteLocation(true);   mIgnoreLostFocus = true;   mAutoCompleteForm.Visible = true;   SetBestSelectedAutoCompleteItem();   mAutoCompleteShown = true;   Focus();   mIgnoreLostFocus = false;  }

      #endregion

      #region Rtf building helper functions

      /// <summary>  /// Set color and font to default control settings.  /// </summary>  /// <param name="sb">the string builder building the RTF</param>  /// <param name="colors">colors hashtable</param>  /// <param name="fonts">fonts hashtable</param>  private void SetDefaultSettings(StringBuilder sb, Hashtable colors, Hashtable fonts)  {   SetColor(sb, ForeColor, colors);   SetFont(sb, Font, fonts);   SetFontSize(sb, (int)Font.Size);   EndTags(sb);  }

      /// <summary>  /// Set Color and font to a highlight descriptor settings.  /// </summary>  /// <param name="sb">the string builder building the RTF</param>  /// <param name="hd">the HighlightDescriptor with the font and color settings to apply.</param>  /// <param name="colors">colors hashtable</param>  /// <param name="fonts">fonts hashtable</param>  private void SetDescriptorSettings(StringBuilder sb, HighlightDescriptor hd, Hashtable colors, Hashtable fonts)  {   SetColor(sb, hd.Color, colors);   if (hd.Font != null)   {    SetFont(sb, hd.Font, fonts);    SetFontSize(sb, (int)hd.Font.Size);   }   EndTags(sb);

      }  /// <summary>  /// Sets the color to the specified color  /// </summary>  private void SetColor(StringBuilder sb, Color color, Hashtable colors)  {   sb.Append(@"/cf").Append(colors[color]);  }  /// <summary>  /// Sets the backgroung color to the specified color.  /// </summary>  private void SetBackColor(StringBuilder sb, Color color, Hashtable colors)  {   sb.Append(@"/cb").Append(colors[color]);  }  /// <summary>  /// Sets the font to the specified font.  /// </summary>  private void SetFont(StringBuilder sb, Font font, Hashtable fonts)  {   if (font == null) return;   sb.Append(@"/f").Append(fonts[font.Name]);  }  /// <summary>  /// Sets the font size to the specified font size.  /// </summary>  private void SetFontSize(StringBuilder sb, int size)  {   sb.Append(@"/fs").Append(size*2);  }  /// <summary>  /// Adds a newLine mark to the RTF.  /// </summary>  private void AddNewLine(StringBuilder sb)  {   sb.Append("//par/n");  }  /// <summary>  /// Ends a RTF tags section.  /// </summary>  private void EndTags(StringBuilder sb)  {   sb.Append(' ');  }  /// <summary>  /// Adds a font to the RTF's font table and to the fonts hashtable.  /// </summary>  /// <param name="sb">The RTF's string builder</param>  /// <param name="font">the Font to add</param>  /// <param name="counter">a counter, containing the amount of fonts in the table</param>  /// <param name="fonts">an hashtable. the key is the font's name. the value is it's index in the table</param>  private void AddFontToTable(StringBuilder sb, Font font, ref int counter, Hashtable fonts)  {    sb.Append(@"/f").Append(counter).Append(@"/fnil/fcharset0").Append(font.Name).Append(";}");   fonts.Add(font.Name, counter++);  }  /// <summary>  /// Adds a color to the RTF's color table and to the colors hashtable.  /// </summary>  /// <param name="sb">The RTF's string builder</param>  /// <param name="color">the color to add</param>  /// <param name="counter">a counter, containing the amount of colors in the table</param>  /// <param name="colors">an hashtable. the key is the color. the value is it's index in the table</param>  private void AddColorToTable(StringBuilder sb, Color color, ref int counter, Hashtable colors)  {    sb.Append(@"/red").Append(color.R).Append(@"/green").Append(color.G).Append(@"/blue")    .Append(color.B).Append(";");   colors.Add(color, counter++);  }

      #endregion

      #region Scrollbar positions functions  /// <summary>  /// Sends a win32 message to get the scrollbars' position.  /// </summary>  /// <returns>a POINT structore containing horizontal and vertical scrollbar position.</returns>  private unsafe Win32.POINT GetScrollPos()  {   Win32.POINT res = new Win32.POINT();   IntPtr ptr = new IntPtr(&res);   Win32.SendMessage(Handle, Win32.EM_GETSCROLLPOS, 0, ptr);   return res;

      }  /// <summary>  /// Sends a win32 message to set scrollbars position.  /// </summary>  /// <param name="point">a POINT conatining H/Vscrollbar scrollpos.</param>  private unsafe void SetScrollPos(Win32.POINT point)  {   IntPtr ptr = new IntPtr(&point);   Win32.SendMessage(Handle, Win32.EM_SETSCROLLPOS, 0, ptr);

      }  #endregion }

    } 

     

     

    using  System; using  System.Runtime; using  System.Runtime.InteropServices; using  HWND  =  System.IntPtr; namespace  UrielGuy.SyntaxHighlightingTextBox {    /// <summary>    /// Summary description for Win32.    /// </summary>    public class Win32    {        private Win32()        {        }        public const int WM_USER = 0x400;        public const int WM_PAINT = 0xF;        public const int WM_KEYDOWN = 0x100;        public const int WM_KEYUP = 0x101;        public const int WM_CHAR = 0x102;        public const int EM_GETSCROLLPOS  =       (WM_USER + 221);        public const int EM_SETSCROLLPOS  =       (WM_USER + 222);        public const int VK_CONTROL = 0x11;        public const int VK_UP = 0x26;        public const int VK_DOWN = 0x28;        public const int VK_NUMLOCK = 0x90;        public const short KS_ON = 0x01;        public const short KS_KEYDOWN = 0x80;        [StructLayout(LayoutKind.Sequential)]        public struct POINT         {            public int x;            public int y;        }        [DllImport("user32")] public static extern int SendMessage(HWND hwnd, int wMsg, int wParam, IntPtr lParam);        [DllImport("user32")] public static extern int PostMessage(HWND hwnd, int wMsg, int wParam, int lParam);        [DllImport("user32")] public static extern short GetKeyState(int nVirtKey);        [DllImport("user32")] public static extern int LockWindowUpdate(HWND hwnd);    }}

    最新回复(0)