我在CodeProject上发现了以下内容。这是有意义的,除非子类控件不处理OCM_消息,这意味着原始消息的默认处理永远不会发生。是否有一个优雅的解决方案,而不是总是同步这个函数发送的消息与子类窗口过程?
LRESULT DefParentProc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch (umsg) {
case WM_NOTIFY:
{
NMHDR* nmhdr = (NMHDR*)lparam;
if (nmhdr->hwndFrom != NULL)
return SendMessage(nmhdr->hwndFrom, umsg + OCM__BASE, wparam, lparam);
break;
}
// All of these provide the control's HHWND in LPARAM
case WM_COMMAND:
case WM_CTLCOLORBTN:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORDLG:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
case WM_VKEYTOITEM:
case WM_CHARTOITEM:
if (lparam != 0)
return SendMessage((HWND)lparam, umsg + OCM__BASE, wparam, lparam);
break;
// All of these provide ID of the control in WPARAM:
case WM_DRAWITEM:
case WM_MEASUREITEM:
case WM_DELETEITEM:
case WM_COMPAREITEM:
if (wparam != 0) {
HWND hwndControl = GetDlgItem(hwnd, wparam);
if (hwndControl)
return SendMessage(hwndControl, umsg + OCM__BASE, wparam, lparam);
}
break;
// Note we do not reflect WM_PARENTNOTIFY -> OCM_PARENTNOTIFY as that
// usually does not make much sense.
}
return DefWindowProc(hwnd, umsg, wparam, lparam);
}发布于 2019-06-26 22:24:46
这里没有真正干净的解决办法。
您可以确保在为未处理的OCM__BASE消息调用DefWindowProc()时,所有子控件都会减去OCM_...。
LRESULT WINAPI DefChildProc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch (umsg) {
...
}
if ((umsg >= OCM__BASE) && (umsg <= OCM__MAX)) {
umsg -= OCM__BASE;
}
return DefWindowProc(hwnd, umsg, wparam, lparam);
}否则,可以让每个OCM_...消息在其WPARAM或LPARAM中携带指向结构的指针,其中结构包含真正的WPARAM/LPARAM和输出LRESULT,然后如果处理给定的OCM_...消息,每个子控件都可以返回TRUE。如果DefWindowProc()返回FALSE,则父程序可以使用原始的WM_...消息调用SendMessage(OCM_...)。
struct OCMInfo
{
LPARAM lParam;
LRESULT lResult;
};
LRESULT WINAPI DefParentProc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch (umsg) {
case WM_NOTIFY:
{
NMHDR* nmhdr = (NMHDR*)lparam;
if (nmhdr->hwndFrom != NULL)
{
OCMInfo info;
info.lParam = lParam;
info.lResult = 0;
if (SendMessage(nmhdr->hwndFrom, umsg + OCM__BASE, wparam, (LPARAM)&info))
return info.lResult;
}
break;
}
// All of these provide the control's HHWND in LPARAM
case WM_COMMAND:
case WM_CTLCOLORBTN:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORDLG:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
case WM_VKEYTOITEM:
case WM_CHARTOITEM:
if (lparam != 0)
{
OCMInfo info;
info.lParam = lParam;
info.lResult = 0;
if (SendMessage((HWND)lparam, umsg + OCM__BASE, wparam, (LPARAM)&info))
return info.lResult;
}
break;
// All of these provide ID of the control in WPARAM:
case WM_DRAWITEM:
case WM_MEASUREITEM:
case WM_DELETEITEM:
case WM_COMPAREITEM:
if (wparam != 0) {
HWND hwndControl = GetDlgItem(hwnd, wparam);
if (hwndControl)
{
OCMInfo info;
info.lParam = lParam;
info.lResult = 0;
if (SendMessage(hwndControl, umsg + OCM__BASE, wparam, (LPARAM)&info))
return info.lResult;
}
}
break;
// Note we do not reflect WM_PARENTNOTIFY -> OCM_PARENTNOTIFY as that
// usually does not make much sense.
}
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
LRESULT WINAPI DefChildProc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch (umsg) {
case OCM__NOTIFY:
{
OCMInfo* info = (OCMInfo*)lparam;
NMHDR* nmhdr = (NMHDR*)(info->lparam);
if (...) {
...
info->lResult = ...;
return TRUE;
}
break;
}
case OCM__COMMAND:
{
OCMInfo* info = (OCMInfo*)lparam;
if (...) {
...
info->lResult = ...;
return TRUE;
}
break;
}
...
}
return DefWindowProc(hwnd, umsg, wparam, lparam);
}https://stackoverflow.com/questions/56780239
复制相似问题