Как обрабатывать необработанное отражение сообщения Win32 в подклассных элементах управления через сообщения OCM_ - PullRequest
0 голосов
/ 26 июня 2019

Я нашел следующее на 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 Ответ

3 голосов
/ 27 июня 2019

Здесь на самом деле нет чистого решения.

Вы можете убедиться, что все дочерние элементы управления вычитают 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 и вывод * 1016.*, а затем каждый дочерний элемент управления может возвращать TRUE, если обрабатывается данное сообщение OCM_....Затем родитель может вызвать DefWindowProc() с исходным сообщением WM_..., если SendMessage(OCM_...) вернет FALSE.

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