如何通过OCM_消息处理未处理的Win32消息反射到附属控件的问题

时间:2019-06-26 20:15:04

标签: winapi controls messaging

我在CodeProject上发现了以下内容。这是有道理的,除非子类控件不处理OCM_消息,这意味着永远不会发生对原始消息的默认处理。是否有一种优雅的解决方案,而不必始终同步此函数与子类Windows过程发送的消息?

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);
}

1 个答案:

答案 0 :(得分:3)

这里真的没有 clean 解决方案。

您可以确保在为未处理的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_...消息在其WPARAMLPARAM中携带一个指向结构的指针,其中该结构包含真实的WPARAM / {{1 }}和输出LPARAM,然后,如果处理了给定的LRESULT消息,则每个子控件都可以返回TRUE。如果OCM_...返回FALSE,则父级可以使用原始DefWindowProc()消息调用WM_...

SendMessage(OCM_...)