В-приложение Win32 есть сообщение для Windows или некоторые другие уведомления, которые будут передаваться в окно ребенка, когда он помещается в другой родительКак окно ребенок реагирует на изменение своего родителя
ответ
Это легко протестировать в приложении 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.
Я бы начал с проверки 'WM_WINDOWPOSCHANGED'. –
Для этого не существует единого уведомления. Однако некоторые фреймворки, такие как VCL Borland, обертывают окна в классах и, таким образом, выдает свои собственные уведомления, когда объекты класса перемещаются из одного родителя в другой (например, VCL имеет CM_CONTROLLISTCHANGING
, CM_CONTROLLISTCHANGE
и CM_CONTROLCHANGE
уведомлений).
Можете ли вы предоставить более подробную информацию о том, что именно вы хотите добиться, обнаружив изменение родительского окна?
Мое окно находится внутри плагина, который динамически вставлен в иерархию окна главной программы, и мне нужно определить, когда он перемещается между разными местами в этой иерархии хоста. – solsberg
Затем я предлагаю вам регистрировать сообщения, которые действительно получает ваше плагин, а затем выбрать наиболее подходящий для ваших нужд. –
Да, это то, что я делаю сейчас, вызывая GetParent(), когда я получаю сообщение WM_WINDOWPOSCHANGED и сравниваю его с предыдущим родительским дескриптором. – solsberg
Сортировка ... Я сделал это, прежде чем использовать обмен сообщениями между Windows и поток для прослушивания на них. Помните, что вы НЕ хотите изменять пользовательский интерфейс из любого потока, а затем тот, который СОЗДАЛ его ...
Вот пример кода родительского окна, которое получает уведомление об изменении одним из его дочерних окон Windows. Тот же принцип применяется, когда вы делаете то, о чем говорите. Родительская Windows на самом деле не накачивает сообщения, пока ребенок открыт, (он есть, но я забываю, что происходит в это время) ... Прошло уже 10 лет с тех пор, как я должен был сделать что-то подобное ... Но приведенный ниже код предназначен для родительского окна с сеткой и дочернего окна «Добавить/редактировать», которое открывается, а когда вы добавляете или редактируете элемент, он обновляет родительский GRID за окном Modal Edit. Это было разработано в 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;
}
Затем в детском окне, я бы отправить сообщение обратно к родителю, когда пришло время Обновить. Я сделал это, создав поток, который просто отправил сообщение, чтобы остальная часть диалога продолжала функционировать ... (Или в вашем случае вы можете отправить сообщение непосредственно в HWND для дочерних Windows, чтобы обновить его. .)
void _cdecl GridUpdateThread(void *ptr)
{
CEnterMeterReadingsDlg *pthis = (CEnterMeterReadingsDlg*)ptr;
if(pthis->NotifyParent())
{
pthis->NotifyParent()->SendMessage(CMeterReadings::GRID_UPDATE_MESSAGE, 0, 0);
}
}
Затем все это в движение, когда пользователь выбрал «СЛЕДУЮЩИЙ» в диалоговом окне, вместо OK или CANCEL ...
_beginthread(GridUpdateThread, NULL, this);
Ну, надеюсь, это поможет вы некоторые, или дать вам некоторые идеи ...
Полезная информация, но я думаю, что вы отвечаете на другой вопрос. –
В моем точном примере да. Но то, что я делал, было способом, которым он мог бы использовать для наблюдения за вещами, возможно, используя переопределение для SetParent() или что-то в этом роде. Примером этого примера было показать, как разговаривать между двумя окнами с помощью потоков и настраиваемых сообщений. Я думаю, он мог бы сделать то, что хотел, использовать метод, как я упоминаю ... В нем нет ничего, что сделало бы для него ... – LarryF
Чтобы уточнить, вы спрашиваете, '' SetParent (hwndChild, hwndNewParent) 'отправляет нет tification to hwndChild? –
Да, или есть ли другой способ для ребенка определить, что было перенесено на другого родителя? – solsberg