【发布时间】:2013-08-24 13:03:17
【问题描述】:
更新:根据要求,我添加了用于创建 Window 及其 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);
}
}
MsgProc:
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。
我不确定我在这里做错了什么或如何正确解决这个问题。
编辑:
根据答案和 cmets,我已将我的代码恢复为仅使用包含 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注册您自己的类有效地替换了原来的类。完成此操作后,将无法再访问原始类,而尝试创建MSFTEDIT_CLASS会改为创建您的类。这就像用另一个文件覆盖一个文件。目前尚不清楚您的目标是什么。是否要在全局范围内部分替换富编辑控件?只有一个窗口?或者您只是想响应来自窗口的消息? -
我试图在一个或多个窗口中创建一个
RichEdit控件,但现在它只是一个。 -
然后创建标准的
MSFTEDIT_CLASS。不要尝试自己编写。就像你说的,如果你使用标准控件,“RichEdit 控件可以完美地绘制和运行。” -
我已经撤消了对代码的更改,因此只有一个用于 Window 的类,它使用我在上面的问题中添加的函数来创建 RichEdit 控件。
-
"如何在 Window 的 MsgProc 中处理来自该控件的消息?"你为什么要处理别人的消息?让他们处理自己的消息。
标签: c++ winapi wndproc richedit