动态变化大小的RichTextBox: "Bottomless RichTexBox"
来源:互联网 发布:视频歌词制作软件 编辑:程序博客网 时间:2024/06/03 17:23
【转载请注明出处: http://blog.csdn.net/lzl124631x】
我在用C#写一个窗体程序, 其中有RichTextBox读取RTF. 我期望RTB的宽度是固定的, 高度能够根据RTF的内容而动态改变. 搜了很多资料还不清楚怎么弄. 暂时找到了以下资料可能有用:
- C#调用API接收发送窗口消息 http://blog.csdn.net/haylhf/article/details/7842174
- C#中 WndProc(ref Message m) 方法怎么用 http://bbs.csdn.net/topics/290047154
- How To Resize RichTextbox Control with Endless Bottom http://support.microsoft.com/kb/257849
- Bottomless Rich Edit Controls http://msdn.microsoft.com/en-us/library/vstudio/dzh15c7k.aspx
- RichTextBox如何自适大小 http://social.msdn.microsoft.com/Forums/en-US/111a2875-dee8-4b42-aed5-d887a26b6926/richtextbox?forum=2212
在第3条中给出了VB的实现方法. MSDN上给出来的, 比较信赖, 所以决定先用VB试一下. 一开始用VS2010尝试建工程发现完全不是一回事儿, 发现应该用Visual Basic6.0来实现, 遂下载之. 在http://xiazai.zol.com.cn/detail/3/29939.shtml下载了一个精简版, 只有5.86MB. 但是缺陷是没有RichTextBox控件, 需要自己下. 搜了下, 需要下载richtx32.ocx放到windows\system32下面, 在http://www.xdowns.com/soft/184/dll/2008/Soft_40499.html下载了一个, 点bat直接帮你放到system32下面了.
打开VB, Ctrl+T(或者"工程">"部件"), 勾选Microsoft Windows Common Dialog Control和Microsoft Rich Textbox Control.
然后按照http://support.microsoft.com/kb/257849/en-us中说的一步一步来:
- Start a new Visual Basic Standard EXE project. Form1 is created by default.
创建一个新的Visual Basic Standard EXE工程. - On the Project menu, select Components. Check the Rich Textbox and Common Dialog controls, and then click OK.
"工程">"部件", 勾选Rich Textbox和Common Dialog控件 - Add a CommandButton, a CommonDialog, and a RichTextBox control to Form1.
向Form1中添加CommandButton, CommonDialog和RichTextBox - In the Properties window, set the ScrollBars property of RichTextBox1 to 2-rtfVertical.
在RichTextBox1的属性窗口中将ScrollBars属性设置为2-rtfVertical. - Add the following code to the General Declarations section of Form1:
向Form1中添加如下代码:Option ExplicitPrivate Sub Form_Load()' Create a Hook and populate a global variable with the Richtextbox hwnd. Call NewWindowProc(Me.hWnd) RichWnd = RichTextBox1.hWndEnd SubPrivate Sub Command1_Click()' Load a file into the richtextbox control With CommonDialog1 .Filter = "All Files|*.*|Text Files|*.txt|RTF Files|*.rtf" .ShowOpen RichTextBox1.FileName = .FileName End WithEnd SubPrivate Sub Form_Resize()' 1.)Populate global variables with the Height and Width of the ' Richtextbox control.' 2.)Set an event mask for the Richtextbox control.' 3.)Send an EM_REQUESTRESIZE Message to the Form. gblWidth = RichTextBox1.Width / Screen.TwipsPerPixelX gblHeight = ((Form1.Height - RichTextBox1.Top) - 450) / _ Screen.TwipsPerPixelY Call SetMask(RichWnd) Call SendMessage(RichWnd, EM_REQUESTRESIZE, 0, 0)End SubPrivate Sub Form_Unload(Cancel As Integer) Call ResetWindProc(Me.hWnd) ' Remove the Windows HookEnd Sub
- On the Project menu, select Add Module to add a BAS module to the project. Module1 is created by default.
"工程">"添加模块" - Add the following code to General Declarations section of Module1:
向Module1中添加如下代码:Option Explicit' Private VariablesPrivate rResize As REQSIZE ' <--- Pointer to REQSIZE StructurePrivate MaskHdr As nmhdr ' <--- Pointer to nmhdr StructurePrivate OldWndProc As LongPrivate Const GWL_WNDPROC = (-4)Private Const WM_USER = &H400Private Const WM_NOTIFY = &H4EPrivate Const SWP_NOMOVE = &H2Private Const SWP_SHOWWINDOW = &H40Private Const EM_GETEVENTMASK = (WM_USER + 59)Private Const EM_SETEVENTMASK = (WM_USER + 69)Private Const ENM_REQUESTRESIZE As Long = &H40000Private Const EN_REQUESTRESIZE = &H701' Public VariablesPublic gblWidth As Long ' <--- Var Holder for Richtext WidthPublic gblHeight As Long ' <--- Var Holder for Richtext HeightPublic Const EM_REQUESTRESIZE = (WM_USER + 65)Public Const VBNullPtr = 0&Public RichWnd As Long ' <--- Var Holder for Richtext HwndPrivate Type nmhdr hwndFrom As Long idfrom As Long code As LongEnd TypePrivate Type rect Left As Long Top As Long Right As Long Bottom As LongEnd TypePrivate Type REQSIZE nmhdr As nmhdr rect As rectEnd TypePublic Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As LongPrivate Declare Function SetWindowLong Lib "user32" Alias _ "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, _ ByVal dwNewLong As Long) As LongPrivate Declare Function CallWindowProc Lib "user32" _ Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _ ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As LongPrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long)Public Declare Function SetWindowPos Lib "user32" _ (ByVal hwnd As Long, ByVal hWndInsAfter As Long, ByVal x As Long, _ ByVal y As Long, ByVal cx As Long, ByVal cy As Long, _ ByVal wFlags As Long) As Long' Call SetWindowLong to instantiate the Window Procedure by passing the' Address of MyWndProc.Public Sub NewWindowProc(fhWnd As Long) On Error Resume Next OldWndProc = SetWindowLong(fhWnd, GWL_WNDPROC, AddressOf MyWndProc)End Sub' Once the Hook is in place, All messages will be processed by this' function. Test for a WM_NOTIFY and parse the lParam to search for a' specific value. In this case we are looking for EN_REQUESTRESIZE in the' nmhdr structure. If an EN_REQUESTRESIZE is found then grab the next' structure(REQSIZE) from the lParam.Public Function MyWndProc(ByVal hwnd As Long, _ ByVal Msg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long On Error Resume Next Select Case Msg Case WM_NOTIFY Call CopyMemory(MaskHdr, ByVal lParam, Len(MaskHdr)) If MaskHdr.code = EN_REQUESTRESIZE Then Call CopyMemory(rResize, ByVal lParam, Len(rResize)) If rResize.rect.Bottom < gblHeight Then Call SetWindowPos(RichWnd, VBNullPtr, _ 0, 0, gblWidth, _ rResize.rect.Bottom, _ SWP_SHOWWINDOW Or SWP_NOMOVE) Else Call SetWindowPos(RichWnd, VBNullPtr, _ 0, 0, _ gblWidth, gblHeight, _ SWP_SHOWWINDOW Or SWP_NOMOVE) End If' By modifying 2 of the above parameters you can create an endless bottom' Richtext control. This may be desirable if you plan to wrap the control' and use it on a web page. To test this, comment the 'If' Statement above' and replace it with the SetWindowPos Function call below.' The control will now Resize itself to its actual contents.' Call SetWindowPos(RichWnd, VBNullPtr, _' 0, 0, _' gblWidth, rResize.rect.Bottom, _' SWP_SHOWWINDOW Or SWP_NOMOVE) End If Case Else ' Handle other messages here. End Select ' Reset windowproc MyWndProc = CallWindowProc(OldWndProc, hwnd, Msg, wParam, lParam)End FunctionPublic Sub ResetWindProc(hwnd As Long) On Error Resume Next ' Call SetWindowLong to remove the Windows Hook from app. Call SetWindowLong(hwnd, GWL_WNDPROC, OldWndProc)End SubPublic Sub SetMask(fhWnd As Long) On Error Resume Next Dim CurrentMask As Long Dim NewMask As Long' Set the Event Mask to be called. CurrentMask = SendMessage(fhWnd, EM_GETEVENTMASK, 0, 0) NewMask = (CurrentMask Or ENM_REQUESTRESIZE) Call SendMessage(fhWnd, EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE)End Sub
- Save and run the project. Note that the control is now being displayed using the height of the contents or the height of the form.
运行工程. 现在RTB的高度可以随着内容变化了!
换一个RTF, 出现滚动条了, 不过轻轻把窗口拉大一下就好了, 代码里还有些问题, 不过我现在只是借鉴, 没关系.
RTB此时取内容高度与窗口高度间的最小值, 如果窗口高度比内容高度小, 会出现滚动条! - Comment out the If statement described in the comments in Module1 of the code sample, and uncomment the SetWindowPos function call following it.
Module1中有几行注释, 上面是一段If代码, 下面是被注释掉的SetWindowPos函数. 注释掉那段If代码, 取消掉SetWindowPos函数的注释.
VB6.0里面注释代码段:
"视图">"工具栏">"编辑"
其中就是注释和取消注释. - Save the project and run it. The RichTextBox control now resizes itself to the height of its contents regardless of the size of the contents.
运行程序, 现在RTB不管内容多大, 都保证是内容的高度, 不会添加滚动条了!
今天就先弄到这里, 改天把这代码改成C#版本. 忍不住吐槽下, 这么一个看似合理简单的功能却要这么费劲!
- 动态变化大小的RichTextBox: "Bottomless RichTexBox"
- C# RichTextBox高度随内容动态变化
- RichTexBox 控件的换行
- 根据webform页面大小的变化动态调整控件的大小
- C# 获取RICHTEXTBOX所有图形的位置和大小
- MFC中控件大小随对话框大小动态变化
- MFC中控件大小随对话框大小动态变化
- 对话框控件大小随窗口的大小变化而变化
- 图片的动态变化
- 固定Textview,字体随着字数的多少字体动态变化大小
- Datagrid数据表格在不同大小的显示器动态变化高度
- C#在RichTexBox里选中某一行的字符
- 【VB6】动态创建RichTextBox
- c#自带的richtextbox实现动态的gif
- 让div的大小随着内容的变化而变化
- 背景图片随网页的变化而变化(指大小)
- 如何让控件随窗体的大小变化而变化
- 表示变化的动态描述
- 南阳ACM6-喷水装置(一)
- vlc 日志输出方法
- GLib 创建自定义事件源
- 理解MySQL——索引与优化
- 将博客搬至CSDN
- 动态变化大小的RichTextBox: "Bottomless RichTexBox"
- 使用node-inspector在线调试Node.js
- AVD简单介绍
- vs2005水晶报表的使用
- [week10]每周总结与工作计划(泛水)
- LeetCode 之 Pascal's Triangle
- HDU 4258 Covered Walkway(斜率优化DP)
- java静态内部类
- ActionBarSherlock注意事项