Как дочернее окно может реагировать на изменение в родительском окне? - PullRequest
4 голосов
/ 05 октября 2010

В приложении Win32 есть сообщение Windows или другое уведомление, которое отправляется дочернему окну, когда оно помещается в другой родительский

Ответы [ 3 ]

2 голосов
/ 05 октября 2010

Это легко проверить в приложении Windows Forms.Вот что я увидел:

msg=0x18 (WM_SHOWWINDOW) hwnd=0x60c60 wparam=0x1 lparam=0x0 result=0x0
msg=0x46 (WM_WINDOWPOSCHANGING) hwnd=0x60c60 wparam=0x0 lparam=0x563e01c result=0x0
msg=0x85 (WM_NCPAINT) hwnd=0x60c60 wparam=0x1 lparam=0x0 result=0x0
msg=0x14 (WM_ERASEBKGND) hwnd=0x60c60 wparam=0xffffffff930119e8 lparam=0x0 result=0x0
msg=0x47 (WM_WINDOWPOSCHANGED) hwnd=0x60c60 wparam=0x0 lparam=0x563e01c result=0x0
msg=0xf (WM_PAINT) hwnd=0x60c60 wparam=0x0 lparam=0x0 result=0x0
msg=0xe (WM_GETTEXTLENGTH) hwnd=0x60c60 wparam=0x0 lparam=0x0 result=0x0
msg=0xd (WM_GETTEXT) hwnd=0x60c60 wparam=0x6 lparam=0x3fd7928 result=0x0

WM_SHOWWINDOW - хорошее время, чтобы проверить, изменился ли родитель.Не уверен на 100%, если это побочный эффект кода WF, который заботится об изменении родителя, шансы довольно высоки.В противном случае для него нет выделенного сообщения, предполагается, что программа уже знает, поскольку она явно вызвала SetParent или SetWindowLongPtr.

0 голосов
/ 05 октября 2010

Вроде ... Я делал это прежде, чем использовать обмен сообщениями между Windows и потоком для их прослушивания. Помните, вы НЕ хотите изменять пользовательский интерфейс из какого-либо потока, а не из того, который его создал ...

Вот пример кода родительского окна, которое получает уведомление об изменении одной из дочерних окон Windows. Тот же принцип применяется при выполнении того, о чем вы говорите. Родительская Windows на самом деле не качает сообщения, пока ребенок открыт (да, но я забываю о том, что происходит у нее в голове) ... Прошло 10 лет с тех пор, как мне пришлось делать что-то подобное ... Но приведенный ниже код предназначен для родительского окна с сеткой и дочерним окном «Добавить / редактировать», которое открывается, и когда вы добавляете или редактируете элемент, оно обновляет родительскую GRID за окном модального редактирования. Это было разработано в MFC, так что вы представляете, что вам просто нужно добавить несколько переменных HWND к вызовам функций, чтобы заставить его работать под Win32, поскольку Win32 и MFC так взаимосвязаны.

Во-первых, в родительском окне я настраиваю поток:

DWORD WINAPI PopulateGridThread(void *ptr)
{
   CMeterReadings *pThis = (CMeterReadings*)ptr;
   pThis->hGridMutex = CreateMutex(NULL, FALSE, "Wims.MeterReadingGridUpdateMutex");
   WaitForSingleObject(pThis->hGridMutex, 0);
   if(WaitForSingleObject(pThis->hGridMutex, 0) != WAIT_OBJECT_0) {
      return -2;
   }
   try {
      if(pThis->m_Get.GetCheck() == FALSE)
      {
         if(pThis->m_Grid.IsEmpty())
         {
            CloseHandle(pThis->hGridMutex);
            CloseHandle(pThis->hThreadHandle);
            pThis->hThreadHandle = INVALID_HANDLE_VALUE;
            pThis->m_DateFilter.EnableWindow(pThis->m_UseDate.GetCheck());
            pThis->m_UseDate.EnableWindow(TRUE);
            pThis->m_MeterFilter.EnableWindow(TRUE);
            return -3;
         }
      }

      pThis->hCursor = LoadCursor(NULL, IDC_APPSTARTING);
      pThis->m_Get.SetCheck(FALSE);
      pThis->m_DateFilter.EnableWindow(FALSE);
      pThis->m_UseDate.EnableWindow(FALSE);
      pThis->m_MeterFilter.EnableWindow(FALSE);
      pThis->m_Grid.PushRow();
      pThis->m_Grid.ResetContent();
      bool        bSuccess = false;
      long        nId = CCommonDialog::GetItemData(pThis->m_MeterFilter);
      bool        bUseDate = pThis->m_UseDate.GetCheck() == TRUE;
      CProDate   dtFilterDate;
      pThis->m_DateFilter.GetTime(dtFilterDate);

      if(nId == NULLCONSTANT || nId == LB_ERR)
      {
          bSuccess  = pThis->m_EquipmentPtr.LoadFirstMeterReading(bUseDate ?   CProDate::GetDateOnly(dtFilterDate) : CProDate::NullDate(), true);
      }
      else
      {
          bSuccess = pThis->m_EquipmentPtr.LoadFirstMeterReadingByMeterId(nId, bUseDate ? CProDate::GetDateOnly(dtFilterDate) : CProDate::NullDate());
   }      
   if(pThis->m_EquipmentPtr.GetRecordsReturned() > 5000) 
   {
      if(ThrowQuestion("This expansion could take a long time.  Do you wish to continue?", pThis) == IDNO)
      {
         bSuccess = false;
      }
   }      
   pThis->m_Get.SetWindowText("&Stop");
   if(bSuccess)
   {
      pThis->m_Grid.Redraw(false);
      do
      {
         pThis->m_Grid.AddGridRow();
         pThis->m_Grid.SetCellFormat(COLUMN_ADJUSTMENT,               "Yes;No");
         pThis->m_Grid.SetCheck(COLUMN_ADJUSTMENT,                    pThis->m_EquipmentPtr.AdjustmentIndc);
         pThis->m_Grid.AddDatesToGrid(pThis->m_EquipmentPtr.ReadingDate,     pThis->m_EquipmentPtr.EffectiveDate);
         pThis->m_Grid.AddTextToGrid(COLUMN_METER,                    pThis->m_EquipmentPtr.MeterDesc);
         /* Cut the rest of the fields, as they aren't important... */
      }
      while(pThis->m_EquipmentPtr.LoadNextMeterReading());
   }
   pThis->m_Grid.FinishGrid();
   pThis->m_Grid.Redraw(true);
   pThis->m_Grid.PopRow();
   pThis->m_Grid.RedrawWindow();
}
CATCH_COM_ERROR("CMeterReadings::PopulateGridThread()")
CloseHandle(pThis->hGridMutex);
CloseHandle(pThis->hThreadHandle);
pThis->hThreadHandle = INVALID_HANDLE_VALUE;
pThis->m_DateFilter.EnableWindow(pThis->m_UseDate.GetCheck());
pThis->m_UseDate.EnableWindow(TRUE);
pThis->m_MeterFilter.EnableWindow(TRUE);
pThis->hCursor = LoadCursor(NULL, IDC_ARROW);
pThis->m_Get.SetWindowText("&Get");
return 1;

}

Затем в дочернем окне я отправлял сообщение родителю, когда пришло время обновляться. Я сделал это, создав поток, который просто отправлял сообщение, чтобы остальная часть диалогового окна продолжала функционировать ... (Или, в вашем случае, вы можете отправить сообщение непосредственно в Child HWND Windows, чтобы обновить его). .)

void _cdecl GridUpdateThread(void *ptr)
{
   CEnterMeterReadingsDlg *pthis = (CEnterMeterReadingsDlg*)ptr;
   if(pthis->NotifyParent())
   {
      pthis->NotifyParent()->SendMessage(CMeterReadings::GRID_UPDATE_MESSAGE, 0, 0);
   }
}

Затем все это было приведено в действие, когда пользователь выбрал «СЛЕДУЮЩИЙ» в диалоговом окне вместо ОК или ОТМЕНА ...

_beginthread(GridUpdateThread, NULL, this);

Что ж, надеюсь, это поможет вам или даст вам некоторые идеи ...

0 голосов
/ 05 октября 2010

Специально для этого нет ни одного уведомления.Однако некоторые инфраструктуры, такие как VCL Borland, переносят окна в классах и, таким образом, выдают свои собственные уведомления, когда объекты класса перемещаются от одного родителя к другому (например, VCL имеет CM_CONTROLLISTCHANGING, CM_CONTROLLISTCHANGE и CM_CONTROLCHANGEуведомления).

Можете ли вы предоставить больше информации о том, чего именно вы хотите достичь, обнаружив изменение в родительском окне?

...