Win32 アプリには、別の親ウィンドウに配置されたときに子ウィンドウに送信される Windows メッセージまたはその他の通知がありますか?
3 に答える
これは、Windows フォーム アプリで簡単にテストできます。これは私が見たものです:
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 は、親が変更されたかどうかを確認するのに適しています。これが、変更された親を処理する WF コードの副作用であるかどうかは 100% 確実ではありませんが、可能性はかなり高いです。それ以外の場合、専用のメッセージはありません。プログラムが SetParent または SetWindowLongPtr を明示的に呼び出しているため、プログラムが既に認識していると想定されます。
これについては、特に単一の通知はありません。ただし、Borland の VCL などの一部のフレームワークは、ウィンドウをクラスでラップするため、クラス オブジェクトがある親から別の親に移動すると、独自の通知を発行します (たとえば、VCL には、、、CM_CONTROLLISTCHANGING
およびCM_CONTROLLISTCHANGE
通知CM_CONTROLCHANGE
があります)。
親ウィンドウの変更を検出することで、正確に何を達成したいのかについて、より多くの情報を提供できますか?
並べ替え... Windows間のメッセージングとそれらをリッスンするスレッドを使用する前にこれを行いました。作成したスレッドから UI を変更したくないことを忘れないでください...
親ウィンドウのコード例を次に示します。これは、その子ウィンドウの 1 つによって変更が通知されます。あなたが話していることをするとき、同じ原則が適用されます。親Windowsは、子が開いている間、実際にはメッセージを送信していません(そうですが、そのときに何を考えていたのか忘れてしまいます)...このようなことをしなければならなかったのは10年ぶりです...ただし、以下のコードは、グリッドを持つ親ウィンドウと、開く子「追加/編集」ウィンドウ用に設計されており、項目を追加または編集すると、モーダル編集ウィンドウの背後にある親 GRID が更新されます。これは MFC で設計されているため、Win32 と MFC は相互に関連しているため、関数呼び出しに HWND 変数を追加して Win32 で機能させるだけでよいと想像できます。
まず、親ウィンドウでスレッドをセットアップします。
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;
}
次に、子ウィンドウで、更新の時間になったときにメッセージを親に送り返します。ダイアログの残りの部分が引き続き機能するように、メッセージを送信するだけのスレッドを作成することでこれを行いました...(または、あなたの場合、チャイルド Windows HWND に直接メッセージを送信して更新することができます.. .)
void _cdecl GridUpdateThread(void *ptr)
{
CEnterMeterReadingsDlg *pthis = (CEnterMeterReadingsDlg*)ptr;
if(pthis->NotifyParent())
{
pthis->NotifyParent()->SendMessage(CMeterReadings::GRID_UPDATE_MESSAGE, 0, 0);
}
}
次に、ユーザーがダイアログで [OK] または [キャンセル] ではなく [次へ] を選択すると、これらすべてが開始されました...
_beginthread(GridUpdateThread, NULL, this);
うまくいけば、これはあなたの助けになるか、いくつかのアイデアを提供します...