- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
更新:根据要求,我添加了用于创建窗口及其 RichEdit 控件的所有代码。
我正在尝试处理用作另一个窗口子项的 RichEdit 控件的窗口消息。
现在,除了我自己的 WndProc
之外,我确实可以使用 RichEdit 控件。问题是,当我设置 wc.lpszClassName = MSFTEDIT_CLASS;
使其与 CreateWindowEx()
中使用的 lpClassName
匹配时, RichEdit 控件不再显示为绘制(即文本等),但是,其 WndProc 函数随后可以处理消息。
窗口的创建:
首先是构造函数:
SubWindow::SubWindow(const wchar_t *szAppNameImport)
{
szAppName = szAppNameImport;
cfmt = CHARFORMATW();
hwnd = HWND();
windowRect = RECT();
editControlHwnd = HWND();
wc = WNDCLASSEX();
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_CLASSDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
}
然后是 Create()
函数:
VOID SubWindow::Create(unsigned int window_startX, unsigned int window_startY, unsigned int windowWidthInput, unsigned int windowHeightInput, HWND parent)
{
windowRect.left = window_startX;
windowRect.top = window_startY;
windowRect.right = windowWidthInput;
windowRect.bottom = windowHeightInput;
if(!RegisterClassEx(&wc))
{
throw std::exception();
}
if((hwnd = CreateWindowEx
(
WS_EX_CLIENTEDGE,
szAppName,
TEXT("Our classy sub window!"),
WS_OVERLAPPEDWINDOW| WS_VISIBLE,
windowRect.left, windowRect.top,
windowRect.right, windowRect.bottom,
parent,
NULL,
wc.hInstance,
NULL))==NULL)
{
throw std::exception();
}
SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)this);
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
}
WndProc:
LRESULT CALLBACK SubWindow::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SubWindow *childWindowPointer = (SubWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(childWindowPointer != NULL)
{
if(childWindowPointer->GetEditControl() == hwnd)
OutputDebugString(L"I SHOULD NOT BE CALLED");
return childWindowPointer->MsgProc(hwnd, uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
消息处理:
LRESULT SubWindow::MsgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(uMsg)
{
case WM_WINDOWPOSCHANGED:
{
GetClientRect(hwnd, &windowRect);
SetWindowPos(editControlHwnd, NULL, windowRect.left, windowRect.top, windowRect.right, windowRect.bottom, SWP_NOZORDER | SWP_NOACTIVATE);
return 0;
}
case WM_DESTROY:
{
OutputDebugString(TEXT("DESTROYING A SUB WINDOW!\n"));
return 0;
}
case WM_PAINT:
{
InvalidateRect (hwnd, NULL, FALSE);
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
return 0;
}
case EM_EXSETSEL:
{
if(hwnd == editControlHwnd)
{
OutputDebugString(L"Text selection changed");
return 0;
}
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
RichEdit 控件绘制和运行完美,显然没有问题,除了它没有使用我定义的 WndProc
。
我不确定我在这里做错了什么或者我该如何正确解决这个问题。
编辑:根据答案和评论,我已将我的代码恢复为仅使用包含 RichEdit 控件的 Window
类,该控件是这样创建的:
void SubWindow::CreateEditControl()
{
std::wstring initialText = TEXT("TestWindow\r\n");
LoadLibrary(L"Msftedit.dll");
GetClientRect(hwnd, &windowRect);
editControlHwnd = CreateWindowEx(0, MSFTEDIT_CLASS, initialText.data(),
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY | WS_VSCROLL | ES_NOHIDESEL,
windowRect.left, windowRect.top,windowRect.right,windowRect.bottom,
hwnd,
NULL, NULL, NULL);
cfmt.cbSize = sizeof(CHARFORMAT);
cfmt.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE;
cfmt.dwEffects = 0;
cfmt.yHeight = 160;
cfmt.crTextColor = RGB(0,0,0);
wcscpy_s(cfmt.szFaceName, TEXT("Tahoma"));
SendMessage(editControlHwnd, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cfmt);
}
如何在 Window 的 MsgProc 中处理来自该控件的消息?
最佳答案
当您使用默认类名 (MSFTEDIT_CLASS
) 创建丰富的编辑控件窗口时,所有消息都将发送到其父窗口。由于您不是那个父窗口,因此您无法处理这些消息。
因此您需要将控件子类化,替换为您自己的 将被直接调用的窗口过程,而不是允许将消息传递给父控件。这很容易做到;我之前在 this answer for a regular edit control 中讨论过它.修改后的示例代码如下所示:
// Stores the old original window procedure for the rich edit control.
WNDPROC wpOldRichEditProc;
// The new custom window procedure for the rich edit control.
LRESULT CALLBACK CustomRichEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
...
}
// Pass the messages you don't process on to the original window procedure.
CallWindowProc(wpOldRichEditProc, hWnd, msg, wParam, lParam);
}
当您创建控件时:
// Create the rich edit control
HWND hWnd = CreateWindowEx(...)
// Subclass it.
wpOldRichEditProc= (WNDPROC)SetWindowLongPtr(hWnd,
GWLP_WNDPROC,
(WNDPROC)CustomRichEditProc);
您还需要确保在销毁控件时取消子类控件。另一个示例演示了如何响应父窗口收到的消息,但这在您的情况下不起作用,因为您没有收到父窗口的消息。相反,您需要从控件中删除子类以响应它自己的 WM_NCDESTROY
。留言:
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)wpOldRichEditProc);
或者,公共(public)控件库的版本 6 引入了一种新的、不易出错的子类化方法,使用 a set of utility functions . (关键功能实际上存在于早期版本中,但没有记录。)考虑到您无法控制实际拥有窗口的进程,这可以说是首选方法。
有两种方法的演示 here on MSDN .
当然,您不必只对单个控件进行子类化。您还可以注册一个自定义窗口类,它的行为方式与内置的 Rich Edit 控件相同,但您仍然可以首先破解该类窗口收到的消息。我无法从问题中判断是否有必要; 听起来您只关心一个控件。
关于c++ - 如何正确处理来自 MSFTEDIT_CLASS (RichEdit) 控件的 Windows 消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18418897/
我有一个包含源代码的 TRichEdit 控件。我想设置单行的背景颜色。 我知道如何设置文本 颜色,但是否也可以设置背景颜色?我不是在谈论整个控件的整个背景颜色,我只是在谈论如何更改一行。 我真的必须
我正在将文本从delphi TRichedit 控件输出到打印机。有一个背景图像,所以我使用具有此逻辑的 EM_FORMATRANGE ... myrichedit.Perform(EM_FORMAT
我创建一个新应用程序,放置 TRichedit 并将 PlainText 属性设置为 true。然后,我运行该应用程序并将一些富格式文本粘贴到 RichEdit 中。 我希望它显示为纯文本,但它会显示
添加一行后,我需要将 RichEdit 滚动到最后。我有一个单独的形式的 RichEdit,我根本不想获得焦点。我尝试了经常建议的解决方案: RichEdit.Lines.Add(someText);
(如果您能更好地理解和定义我的问题,请有人编辑标题。) 我遇到的问题是 RichEdit 的样式格式“恢复”回默认的“无”又名 [],然后返回到我设置的任何内容,粗体或斜体示例。 问题所在 - 我认为
RichEdit 控件在成为其他控件的父控件时停止绘制文本。 这是一个功能还是一个错误?是否可以使 RichEdit 成为其他控件的父控件? 查看下一个应用: -- Form1.dfm --- obj
我希望 RichEdit 处理超链接,因此我按照以下说明进行操作:http://delphi.about.com/od/vclusing/l/aa111803a.htm 以下是我对代码所做的更改: i
当我使用多个 RichEdit 控件时,我的行为非常奇怪: LoadLibrary("Msftedit.dll"); RichEdit = CreateWindow("RICHEDIT50W", ""
我想向 RichEdit 控件添加彩色文本行。但我面临的问题是颜色变化不仅限于我选择的文本。我所做的是: 获取当前光标位置 -> 插入文本 -> 获取光标位置 -> 选择范围 -> 为其着色 -> 取
我需要你的帮助!所以,我正在创建一个带有语法高亮器的 RichEdit,我是这样做的: SendMessage(hWin, WM_SETREDRAW, false, 0);
有人知道是否有类似 Memo/RichEdit 的东西吗?需求:对行进行编号,从流中加载大文件(超过 5 MB)。 最佳答案 Developer Express有一套广泛的 VCL 组件,其中包括一个
如何在 RichEdit 中将某一特定行加粗? 最佳答案 丰富的编辑控件中的格式设置如下: 选择要应用格式的文本。 将该格式应用于所选内容。 事情是这样的: RichEdit1.SelStart :=
我有一个 Richedit,允许我的用户格式化和查看我的应用程序中显示的错误消息。 我现在需要能够仅将文本(无格式)导出到他们的故障单系统使用的另一个数据库。 我已经尝试了所有我能想到的纯文本组合,但
我以前从来不需要使用 TRichEdit,一直使用 TMemo。 当我添加 TMemo 等文本时,我希望 RichEdit 自动滚动到末尾。看看添加一些数据后的样子: 如您所见,滚动条保留在顶部,但我
我在计算 Richedit (Delphi XE) 中的字符数时遇到问题。对于每一个新行,我都会多得到两个字符,但在文本中它们不存在。 示例:这里有 15 个字符,但由于换行,richedit 给出了
我试图在 RichEdit 中保存然后恢复垂直滚动位置。 存储滚动位置的全局变量: SI: TScrollInfo; 此代码保存滚动位置: FillChar( SI, SizeOf(SI), #0 )
Delphi 中的大多数 TWinControl 后代都有一个重写方法 CreateParams 来定义它的子类,例如:'EDIT'、'COMBOBOX'、'BUTTON'、'RICHEDIT' 等。
如果您在 Richedit 中加载一些文本,然后单击鼠标左键 + 移动鼠标滚轮,文本将放大或缩小,而不会丢失文本大小格式。 是否有一种简单的方法可以通过几行代码来实现此功能(放大/缩小)? 谢谢 射线
我试图在 RichEdit 中保存然后恢复垂直滚动位置。 存储滚动位置的全局变量: SI: TScrollInfo; 此代码保存滚动位置: FillChar( SI, SizeOf(SI), #0 )
我有一个 TRichEdit。当我选择一些文本并单击另一个元素时,所选文本的选择消失。有没有办法保持这个选择,当 TRichEdit 失去它的焦点时?谢谢! 最佳答案 TRichEdit 有一个属性H
我是一名优秀的程序员,十分优秀!