2013-08-02 3 views
5

나는 여러 가지 질문을 알고 있지만 나는 모든 대답을 이해할 수 없기 때문에 묻습니다. 나는 RichTextBox을 가지고 있고 사용자가 현재 커서 위치에 이미지를 삽입 할 수 있기를 원합니다.서식있는 텍스트 상자에 커서 위치에 이미지 삽입

Clipboard을 사용하여 이미지를 설정 한 다음 서식있는 텍스트 상자에 붙여 넣으려고했습니다. 이것은 작동하지만 사용자에게 알리지 않고 cliboard에서 데이터를 변경하므로 나쁜 습관을 들었다.

은 내가
private bool CheckIfImage(string filename) 
    { 
     if (filename.EndsWith(".jpeg")) { return true; } 
     else if (filename.EndsWith(".jpg")) { return true; } 
     else if (filename.EndsWith(".png")) { return true; } 
     else if (filename.EndsWith(".ico")) { return true; } 
     else if (filename.EndsWith(".gif")) { return true; } 
     else if (filename.EndsWith(".bmp")) { return true; } 
     else if (filename.EndsWith(".emp")) { return true; } 
     else if (filename.EndsWith(".wmf")) { return true; } 
     else if (filename.EndsWith(".tiff")) { return true; } 
     else { return false; } 
    } 

    private void openFileDialog2_FileOk(object sender, CancelEventArgs e) 
    { 
     if (CheckIfImage(openFileDialog2.FileName.ToLower()) == true) 
     { 
      Image img = Image.FromFile(openFileDialog2.FileName); 
      string setData = (String)Clipboard.GetData(DataFormats.Rtf); 

      Clipboard.SetImage(img); 
      rtbType.Paste(); 

      Clipboard.SetData(DataFormats.Rtf, setData); 
     } 
     else 
     { 
      MessageBox.Show("Invalid Image File Selected"); 
     } 
    } 

Pls는이 작업을 수행하는 더 나은 방법이

을 시도 무엇?

+0

가능한 조합 : http://stackoverflow.com/questions/542850/how-can-i-insert-an-image-into-a-richtextbox –

+0

@DmitryBychenko 그 링크는'vb.net'을위한 것입니다 ... –

답변

5

게시 된 솔루션 here을 사용하여 완전한 기능의 예를 준비했습니다.

한스 패전트 (Hans Passant)는 다음과 같이 말했습니다. 솔루션은 매우 까다 롭고이를 달성하기위한 몇 가지 유효한 대안이 있습니다.

private enum EmfToWmfBitsFlags 
    { 
     EmfToWmfBitsFlagsDefault = 0x00000000, 
     EmfToWmfBitsFlagsEmbedEmf = 0x00000001, 
     EmfToWmfBitsFlagsIncludePlaceable = 0x00000002, 
     EmfToWmfBitsFlagsNoXORClip = 0x00000004 
    }; 

    private struct RtfFontFamilyDef 
    { 
     public const string Unknown = @"\fnil"; 
     public const string Roman = @"\froman"; 
     public const string Swiss = @"\fswiss"; 
     public const string Modern = @"\fmodern"; 
     public const string Script = @"\fscript"; 
     public const string Decor = @"\fdecor"; 
     public const string Technical = @"\ftech"; 
     public const string BiDirect = @"\fbidi"; 
    } 

    [DllImport("gdiplus.dll")] 
    private static extern uint GdipEmfToWmfBits(IntPtr _hEmf, 
     uint _bufferSize, byte[] _buffer, 
     int _mappingMode, EmfToWmfBitsFlags _flags); 


    private string GetFontTable(Font font) 
    { 
     var fontTable = new StringBuilder(); 
     // Append table control string 
     fontTable.Append(@"{\fonttbl{\f0"); 
     fontTable.Append(@"\"); 
     var rtfFontFamily = new HybridDictionary(); 
     rtfFontFamily.Add(FontFamily.GenericMonospace.Name, RtfFontFamilyDef.Modern); 
     rtfFontFamily.Add(FontFamily.GenericSansSerif, RtfFontFamilyDef.Swiss); 
     rtfFontFamily.Add(FontFamily.GenericSerif, RtfFontFamilyDef.Roman); 
     rtfFontFamily.Add("UNKNOWN", RtfFontFamilyDef.Unknown); 

     // If the font's family corresponds to an RTF family, append the 
     // RTF family name, else, append the RTF for unknown font family. 
     fontTable.Append(rtfFontFamily.Contains(font.FontFamily.Name) ? rtfFontFamily[font.FontFamily.Name] : rtfFontFamily["UNKNOWN"]); 
     // \fcharset specifies the character set of a font in the font table. 
     // 0 is for ANSI. 
     fontTable.Append(@"\fcharset0 "); 
     // Append the name of the font 
     fontTable.Append(font.Name); 
     // Close control string 
     fontTable.Append(@";}}"); 
     return fontTable.ToString(); 
    } 

    private string GetImagePrefix(Image _image) 
    { 
     float xDpi, yDpi; 
     var rtf = new StringBuilder(); 
     using (Graphics graphics = CreateGraphics()) 
     { 
      xDpi = graphics.DpiX; 
      yDpi = graphics.DpiY; 
     } 
     // Calculate the current width of the image in (0.01)mm 
     var picw = (int)Math.Round((_image.Width/xDpi) * 2540); 
     // Calculate the current height of the image in (0.01)mm 
     var pich = (int)Math.Round((_image.Height/yDpi) * 2540); 
     // Calculate the target width of the image in twips 
     var picwgoal = (int)Math.Round((_image.Width/xDpi) * 1440); 
     // Calculate the target height of the image in twips 
     var pichgoal = (int)Math.Round((_image.Height/yDpi) * 1440); 
     // Append values to RTF string 
     rtf.Append(@"{\pict\wmetafile8"); 
     rtf.Append(@"\picw"); 
     rtf.Append(picw); 
     rtf.Append(@"\pich"); 
     rtf.Append(pich); 
     rtf.Append(@"\picwgoal"); 
     rtf.Append(picwgoal); 
     rtf.Append(@"\pichgoal"); 
     rtf.Append(pichgoal); 
     rtf.Append(" "); 

     return rtf.ToString(); 
    } 

    private string getRtfImage(Image image) 
    { 
     // Used to store the enhanced metafile 
     MemoryStream stream = null; 
     // Used to create the metafile and draw the image 
     Graphics graphics = null; 
     // The enhanced metafile 
     Metafile metaFile = null; 
     try 
     { 
      var rtf = new StringBuilder(); 
      stream = new MemoryStream(); 
      // Get a graphics context from the RichTextBox 
      using (graphics = CreateGraphics()) 
      { 
       // Get the device context from the graphics context 
       IntPtr hdc = graphics.GetHdc(); 
       // Create a new Enhanced Metafile from the device context 
       metaFile = new Metafile(stream, hdc); 
       // Release the device context 
       graphics.ReleaseHdc(hdc); 
      } 

      // Get a graphics context from the Enhanced Metafile 
      using (graphics = Graphics.FromImage(metaFile)) 
      { 
       // Draw the image on the Enhanced Metafile 
       graphics.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height)); 
      } 

      // Get the handle of the Enhanced Metafile 
      IntPtr hEmf = metaFile.GetHenhmetafile(); 
      // A call to EmfToWmfBits with a null buffer return the size of the 
      // buffer need to store the WMF bits. Use this to get the buffer 
      // size. 
      uint bufferSize = GdipEmfToWmfBits(hEmf, 0, null, 8, EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault); 
      // Create an array to hold the bits 
      var buffer = new byte[bufferSize]; 
      // A call to EmfToWmfBits with a valid buffer copies the bits into the 
      // buffer an returns the number of bits in the WMF. 
      uint _convertedSize = GdipEmfToWmfBits(hEmf, bufferSize, buffer, 8, EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault); 
      // Append the bits to the RTF string 
      foreach (byte t in buffer) 
      { 
       rtf.Append(String.Format("{0:X2}", t)); 
      } 
      return rtf.ToString(); 
     } 
     finally 
     { 
      if (graphics != null) 
       graphics.Dispose(); 
      if (metaFile != null) 
       metaFile.Dispose(); 
      if (stream != null) 
       stream.Close(); 
     } 
    } 

I : 필요한 모든 방법이 여기에

private void embedImage(Image img) 
    { 
     var rtf = new StringBuilder(); 

     // Append the RTF header 
     rtf.Append(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1033"); 
     // Create the font table using the RichTextBox's current font and append 
     // it to the RTF string 
     rtf.Append(GetFontTable(this.Font)); 
     // Create the image control string and append it to the RTF string 
     rtf.Append(GetImagePrefix(img)); 
     // Create the Windows Metafile and append its bytes in HEX format 
     rtf.Append(getRtfImage(img)); 
     // Close the RTF image control string 
     rtf.Append(@"}"); 
     richTextBox1.SelectedRtf = rtf.ToString(); 
    } 

:

private bool CheckIfImage(string filename) 
{ 
     var valids = new[] {".jpeg", ".jpg", ".png", ".ico", ".gif", ".bmp", ".emp", ".wmf", ".tiff"}; 
     return valids.Contains(System.IO.Path.GetExtension(filename)); 
} 

private void openFileDialog2_FileOk(object sender, CancelEventArgs e) 
{ 
    if (CheckIfImage(openFileDialog2.FileName.ToLower()) == true) 
     embedImage(Image.FromFile(openFileDialog2.FileName)); 
    else 
     MessageBox.Show("Invalid Image File Selected"); 
} 

이는 embedImage 방법 : BTW

,이 (rewrited) 코드입니다 이것을 자신의 UserControl으로 감쌀 것을 제안합니다.

+0

매우 복잡한 감사 tho. 그것은 효과가 있었다.나는 곧 이해할 것이다 –

+0

이것은 거의 나의 대답이었다. 그러나 내가이 방법으로 그들을 더할 때 이미지는 가장자리 주위에 품질을 잃어 버리고있는 것처럼 보인다. 이것이 일어날 수있는 이유를 말할 수 있을지 확실하지 않습니다. http://imgur.com/6TCzKkv의 예 – Natzely

2

OLE (개체 연결 및 포함)에 대한 RichTextBox의 지원은 역사적인 사고입니다. OLE는 죽은 기술이며 오랫동안 많이 사용되지 않았습니다. 확실히 .NET이 완전히 그것을 지원하지 않는 것은 죽음의 결정이었습니다. 네이티브 RichEdit 컨트롤에서 OLE 지원을 제거하는 것은 현명했지만 너무 많은 고대 응용 프로그램이 손상되었을 것입니다. .NET RichTextBox 클래스 자체는 기본 구성 요소의 작은 래퍼 일 뿐이며 해당 구성 요소의 기능을 추가하거나 뺍니다.

따라서 .NET에서 OLE API를 사용하는 간단한 방법은 없습니다. 클립 보드를 통한 복사/붙여 넣기가 여전히 작동한다는 사실은 사고 일뿐입니다. .NET은 그 작업과 관련이 없으므로 멈추는 데 무력합니다.

그래, 여전히 클립 보드를 통해 작동하며이 기능을 사용하는 유일한 방법입니다. 확실히 더 나은 대안이 있습니다. WebBrowser 또는 Word interop과 같은 기능을 사용하면 유연성이 훨씬 높아집니다. PDF 래퍼가 많이 사용됩니다. WPF는 복합 문서를 잘 지원합니다. 기타.

+0

기본적으로 그는 자신의 TextBox (또는 RichTextBox) 래퍼를 만들어야합니다. – KappaG3

+0

좋아 .. 정보 주셔서 감사합니다 –

+1

@ Precious1tj 사실 당신이 원하는 것을 해결할 수 있지만 상당히 복잡합니다, 여기 당신이 더 많은 것을 연구 할 수있는 링크입니다 http://www.codeproject.com/Articles/4544/Insert- 일반 텍스트 및 이미지 - RichTextBox-at-R –

0

WPF RichTextBox를 사용하여 WinForms 창에서 호스팅 할 수 있습니다. WPF로 커서 위치에 이미지를 삽입 할 수 있습니다.

관련 문제