windows sdk编程系列文章
更新时间:2023-10-18 17:15:01 阅读量: 综合文库 文档下载
- windows10推荐度:
- 相关推荐
windows sdk编程系列文章 ---- RichEdit控件基础知识之四 2008-05-08 09:21
分析:
例子程序首先载入RichEdit DLL, 在这里是 riched20.dll. 如果DLL载入失败,就返回 Windows.
hRichEdit = LoadLibrary(RichEditDLL); if(!hRichEdit) {
MessageBox(0,NoRichEdit,AppName,MB_OK|MB_ICONERROR); return 0; }
成功载入DLL后,我们继续创建一个常规窗口,作为RichEdit的父窗口。在 WM_CREATE 处理函数里,我们创建一个RichEdit控件:
hwndRichEdit =
CreateWindowEx(WS_EX_CLIENTEDGE,RichEditClass,NULL,ES_MULTILINE | WS_CHILD |WS_VISIBLE |WS_VSCROLL |WS_HSCROLL |ES_NOHIDESEL,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hWnd,(HMENU)RichEditID,g_hInstance,NULL);
注意在这里我们指定了 ES_MULTILINE 风格,否则创建的会是一个单行的控件。
SendMessage(hwndRichEdit,EM_LIMITTEXT,-1,0);
创建了RichEdit控件之后,我们必须设置新的正文大小。缺省时,RichEdit控件具有64K的正文大小限制,跟简单的多行Edit控件相同。我们需要扩展这个限制,允许用来操作更大的文件。在上一个代码行里,我们指定了大小为 -1, 大小总计为 0FFFFFFFFh 字节, 是一个很大的数值了。
SetColor();
下一步,我们设置正文/背景色 。 因为这个操作可以在程序中的其他部分执行,我把这些代码放到一个叫SetColor的函数里。
void SetColor() {
CHARFORMAT cfm;
SendMessage(hwndRichEdit,EM_SETBKGNDCOLOR,0,BackgroundColor);
设置RichEdit控件的背景色是一个很简单的操作:只需发送 EM_SETBKGNDCOLOR 信息给
RIchEdit控件就行了。(如果你使用多行Edit控件,你必须处理 WM_CTLCOLOREDIT 消息)。缺省的背景色是白色的。
RtlZeroMemory(&cfm,sizeof(cfm)); cfm.cbSize = sizeof(cfm); cfm.dwMask = CFM_COLOR;
cfm.crTextColor = TextColor;
设置好背景色之后,我们填充 CHARFORMAT 的成员,以便用来设置设置正文颜色。应该注意的是我们使用该结构的大小来填充cbSize 成员,这样RichEdit 控件就知道我们发送的是CHARFORMAT, 而不是 CHARFORMAT2。 dwMask 只使用了一个 CFM_COLOR 标志, 因为我们只想设置正文颜色,同时往 crTextColor 里填入我们想要的正文颜色值.
SendMessage(hwndRichEdit,EM_SETCHARFORMAT,SCF_ALL,(LPARAM)&cfm); }
设置好颜色后,你必须要清空 Undo 缓冲区,因为更改正文/背景颜色的操作是可撤消的(Undo-able),更改颜色时在缓冲区里留下了Undo信息。我们可以发送 EM_EMPTYUNDOBUFFER 消息来实现这个操作。
SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER,0,0 );
填充好 CHARFORMAT 结构, 我们发送 EM_SETCHARFORMAT 消息给RichEdit控件,在wParam中指定 SCF_ALL 标志,说明我们想把正文格式应用于控件中的所有正文。 注意在我们第一次创建RichEdit控件时,我们没有指定它的大小/位置。这是因为我们想它覆盖父窗口的全部客户区。当父窗口大小改变时,我们就跟着改变RichEdit控件的大小。
case WM_SIZE:
MoveWindow(hwndRichEdit,0,0,LOWORD(lParam),HIWORD(lParam),TRUE); break;
在上面的程序片段, 我们使用了在 lParam中的客户区的新尺寸,通过 MoveWindow来改变RichEdit的大小 。
当用户点击文件 File/Edit 菜单条时,我们处理 WM_INITPOPUPMENU 消息,因此我们可以在显示子菜单给用户之前准备好各个子菜单项的状态。譬如,如果已经有一个文件在RichEdit控件中打开了,我们想禁止Open菜单项同时使能其他的菜单项。
对于这种情况下的File菜单条, 我们使用变量 FileOpened 来作为标志表示是否有一个文件已经打开了。如果这个变量是TRUE值,我们知道已经有一个文件被打开了。
case WM_INITMENUPOPUP: if(LOWORD(lParam) == 0)
{
if(FileOpened) {
EnableMenuItem((HMENU)wParam,IDM_OPEN,MF_GRAYED);
EnableMenuItem((HMENU)wParam,IDM_CLOSE,MF_ENABLED);
EnableMenuItem((HMENU)wParam,IDM_SAVE,MF_ENABLED);
EnableMenuItem((HMENU)wParam,IDM_SAVEAS,MF_ENABLED); } else {
EnableMenuItem((HMENU)wParam,IDM_OPEN,MF_ENABLED);
EnableMenuItem((HMENU)wParam,IDM_CLOSE,MF_GRAYED);
EnableMenuItem((HMENU)wParam,IDM_SAVE,MF_GRAYED);
EnableMenuItem((HMENU)wParam,IDM_SAVEAS,MF_GRAYED); } }
正如你所见的,如果有一个文件已经打开了,我们将Open菜单项变灰禁止并将其他菜单项都使能。跟TRUE值相反的是 FileOpened 值为FALSE.
在这种情况下的EDIT菜单条我们需要先检查RichEdit控件/剪贴板的状态。
if(SendMessage(hwndRichEdit,EM_CANPASTE,CF_TEXT,0))
EnableMenuItem((HMENU)wParam,IDM_PASTE,MF_ENABLED); else
EnableMenuItem((HMENU)wParam,IDM_PASTE,MF_GRAYED);
我们首先发送 EM_CANPASTE 消息,来检查剪贴板里是否存在可用的正文。如果有的话,SendMessage 返回 TRUE ,我们就将 Paste 菜单项使能。如果没有的话,我们将该菜单项变灰禁止。
if(SendMessage(hwndRichEdit,EM_CANUNDO,0,0))
EnableMenuItem((HMENU)wParam,IDM_UNDO,MF_ENABLED); else
EnableMenuItem((HMENU)wParam,IDM_UNDO,MF_GRAYED);
过发送 EM_CANUNDO 消息来检查Undo 缓冲区是否为空,如果不空,SendMessage 返回 TRUE ,我们就使能 Undo 菜单项。
if(SendMessage(hwndRichEdit,EM_CANREDO,CF_TEXT,0))
EnableMenuItem((HMENU)wParam,IDM_REDO,MF_ENABLED); else
EnableMenuItem((HMENU)wParam,IDM_REDO,MF_GRAYED);
我们通过发送 EM_CANREDO 消息给 RichEdit 控件来检查 Redo 缓冲区。如果不空的话,SendMessage 返回 TRUE,我们就使能 Redo 菜单项。
SendMessage(hwndRichEdit,EM_EXGETSEL,0,(LPARAM)&chrg); if(chrg.cpMin == chrg.cpMax) {
EnableMenuItem((HMENU)wParam,IDM_COPY,MF_GRAYED);
EnableMenuItem((HMENU)wParam,IDM_CUT,MF_GRAYED);
EnableMenuItem((HMENU)wParam,IDM_DELETE,MF_GRAYED); } else {
EnableMenuItem((HMENU)wParam,IDM_COPY,MF_ENABLED);
EnableMenuItem((HMENU)wParam,IDM_CUT,MF_ENABLED);
EnableMenuItem((HMENU)wParam,IDM_DELETE,MF_ENABLED); }
最后,我们通过发送 EM_EXGETSEL 消息来检查是否存在当前选定的正文,该消息使用一个 CHARRANGE 结构,定义如下:
typedef struct _charrange { LONG cpMin; LONG cpMax; } CHARRANGE;
cpMin 包含紧接在范围中的第一个字符之前的字符的位置索引。 cpMax 包含紧跟在范围中的最后一个字符之后的的字符的位置索引。
EM_EXGETSEL 返回后,CHARRANGE 结构就会被用选择范围的开始和结束位置索引所填充。如果没有当前选定,cpMin 和 cpMax 就会是同样的数值,我们就将 Cut/Copy/Delete 菜
单项变灰禁止。
当用户点击 Open 菜单项,我们就显示一个打开文件的对话框,如果用户选择了一个文件,我们就打开该文件并将其内容流入RichEdit 控件中。 hFile =
CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hFile != INVALID_HANDLE_VALUE) {
editstream.dwCookie = (DWORD)hFile; editstream.pfnCallback = StreamInProc;
SendMessage(hwndRichEdit,EM_STREAMIN,SF_TEXT,(LPARAM)&editstream); 使用 CreateFile成功打开文件后,我们填充EDITSTREAM 结构,以便准备发送 EM_STREAMIN 消息我们选择通过 dwCookie 成员发送打开文件的句柄,并在 pfnCallback 成员中传递流回调函数的地址。 流回调函数本身是简单基本的。
DWORD CALLBACK StreamInProc(DWORD hFile,LPBYTE pBuffer,long NumBytes,long *pBytesRead) {
return
(ReadFile((HANDLE)hFile,pBuffer,NumBytes,(LPDWORD)pBytesRead,0) ^ 1); }
你可以看到流回调函数的所有参数跟 ReadFile 函数 完美匹配。而且ReadFile 的返回值是是跟 1 经过 XOR异或运算的,因此如果它返回 1 (成功),实际返回的值的是0,反之亦然。
SendMessage(hwndRichEdit,EM_SETMODIFY,FALSE,0); CloseHandle(hFile); FileOpened = TRUE; }
消息EM_STREAMIN 返回后, 意味着流操作已经完成。实际上,我们必需检查 EDITSTREAM 结构的 dwError 成员。
RichEdit (和 Edit) 控件支持一个标志,用来指示其内容时候被改变了。我们可以通过发送 EM_GETMODIFY 消息给控件来得到这个标志的值。
如果控件内容被改变了的话,SendMessage 返回 TRUE。因为我们将正文流入控件,也是一种改变。所以我们必需设置修改标志为FALSE,
可以通过给控件发送EM_SETMODIFY 消息,令其 wParam==FALSE 使控件的修改标志在流入操作完成后重新开始。然后我们马上就关闭文件并设置变量 FileOpened 为 TRUE 来说明已经打开了一个文件。
当用户点击 Save/SaveAs 菜单项,我们使用 EM_STREAMOUT 消息来将RichEdit控件的内容输出到一个文件中。跟流入回调函数一样,流出回调函数本身也是很简单的。它也是跟 WriteFile完美匹配.
正文操作象Cut/Copy/Paste/Redo/Undo 等通过发送单个消息给控件是很容易实现的,这些消息分别是 WM_CUT/WM_COPY/WM_PASTE/WM_REDO/WM_UNDO 。 删除/选择全部正文的操作如下:
case IDM_DELETE:
SendMessage(hwndRichEdit,EM_REPLACESEL,TRUE,0); break;
case IDM_SELECTALL: chrg.cpMax = -1; chrg.cpMin = 0;
SendMessage(hwndRichEdit,EM_EXSETSEL,0,(LPARAM)&chrg); break;
删除操作影响到当前的选定。我发送 EM_REPLACESEL 消息,传递一个 NULL 字符串,RichEdit 控件将会用空串来替代当前选定的正文串。
选择全部正文的操作通过发送 EM_EXSETSEL 消息,指定 cpMin==0 和 cpMax==-1 的数值来选择所有的正文。
当用户选择 Option 菜单条,我们显示一个对话框,显示当前的背景/正文颜色。
当用户点击任意一个颜色框,它会显示颜色选择对话框。\颜色框\实际上是一个具有 SS_NOTIFY 和 WS_BORDER 风格标志的静态控件。具有 SS_NOTIFY 标志的静态控件会将在上面的鼠标动作通知给父窗口,譬如BN_CLICKED (STN_CLICKED). 这个就是窍门了!
case IDC_BACKCOLORBOX:
RtlZeroMemory(&clr,sizeof(clr)); clr.lStructSize = sizeof(clr); clr.hwndOwner = hWnd;
clr.hInstance = (HWND)g_hInstance; clr.rgbResult = BackgroundColor; clr.lpCustColors = CustomColors;
clr.Flags = CC_ANYCOLOR | CC_RGBINIT; if(ChooseColor(&clr)) {
BackgroundColor = clr.rgbResult;
InvalidateRect(GetDlgItem(hWnd,IDC_BACKCOLORBOX),0,TRUE); }
break;
当用户点击任意一个颜色框时,我们会填充 CHOOSECOLOR 结构的成员并调用
ChooseColor 来显示颜色选择对话框。如果用户选择了一种颜色,颜色值会在 rgbResult 成员中返回,我们把改值保存在变量 BackgroundColor 中。之后,我们通过用颜色框句柄调用InvalidateRect 函数来强迫颜色框进行重画。 颜色框会发送 WM_CTLCOLORSTATIC 消息给父窗口.
if(GetDlgItem(hWnd,IDC_BACKCOLORBOX) == (HWND)lParam) {
return (int)CreateSolidBrush(BackgroundColor); }
在 WM_CTLCOLORSTATIC 消息处理中,我们把在 lParam 传递进来的静态控件的句柄跟那两个颜色框的句柄作比较。如果值匹配的话,我们就使用变量中颜色值来创建一个新画刷并立刻返回。静态控件将会使用新创建的画刷来重画其背景。
技术成就梦想
类别:windows sdk开发 |
| 添加到搜藏 | 分享到i贴吧 | 浏览(631)
| 评论 (0)
上一篇:windows sdk编程系列文章 ---- R... 下一篇:windows sdk编程系列文章 ---- R...
相关文章:
? VC中在对话框上使用Rich Edit控... ? RichEdit控件加载背景图片 - 转如何在 Visual C++6.0 中使用 ? ? RichEdit控件如何响应鼠标单击??Ri...
? RichEdit 控件基础知识 ? RichEdit控件参考手册
类似QQ的表情,在RichEdit控件
? RichEdit控件中插入图片 ?
中...
查找QQ输入聊天内容的RichEditvb6里TextBox烦心的地方……又? ? 控... 被...更多>>
最近读者:
登录后,您就出现在这里。
zhangxl1菜菜结lctqzq
17晶
正在阅读:
windows sdk编程系列文章10-18
少先队三字歌手抄报02-16
测量试题库05-10
波普解析 偶合常数计算方法 及 例题07-29
吃货弟弟作文600字06-20
青年员工座谈会方案12-15
MCM_优秀论文08-29
十七冶三标一体化管理体系运行记录表格汇编(第7版第0次修改) -03-09
统计学简答题及部分名词解释09-12
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- windows
- 编程
- 系列
- 文章
- sdk
- 关于举办南京农业大学研究生会第二届“精英计划”骨干成员训练营的通知
- 绿色生态县建设调研报告
- 矿井开拓设计
- 性别冲突与广告 - 跨性别广告评析 - 图文
- 学习李新民心得体会1
- 江西省历年专升本英语试题
- Exchange2013安装设置及优化
- 电大国际经济法考试材料 - 图文
- “十三五”重点项目-汽车高压油管燃油系统项目申请报告
- 我国电子商务企业产融结合比较分析
- 陕西省2016届中考语文考前押题记叙文阅读题(含解析)
- 专业英语学习心得体会
- 数理系11级数1班团日活动申请材料 - 图文
- 武进区卢家巷实验学校学习摘记 - 图文
- 五年级上小数的加法和减法教案 苏教版
- 盲人协会章程
- 科大概率模拟试题3套
- 男女之间有没有纯粹的友谊一辩辩词
- 五心心得体会
- 青年创新创效活动管理办法