2010-10-04 47 views
4

的變化在一個Win32應用程序是有當它被放置到不同的父子窗口如何響應其父

+0

只是爲了澄清,你問是否'SetParent(hwndChild,hwndNewParent)'發送一個不通向hwndChild? – 2010-10-04 22:30:11

+1

是的,還是有任何其他方式讓孩子確定已被移到不同的父母身上? – solsberg 2010-10-04 22:54:46

回答

2

這是將被髮送到一個子窗口Windows消息或一些其它的通知易於在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將是一個檢查父母是否改變的好時機。不是100%確定,如果這是WF代碼照顧改變的父母的副作用,那麼賠率相當高。否則沒有專門的消息,假設程序已經知道,因爲它明確地調用SetParent或SetWindowLongPtr。

+0

我會先嚐試使用'WM_WINDOWPOSCHANGED'。 – 2010-10-04 23:07:02

0

沒有針對此的專門通知。但是,像Borland的VCL這樣的一些框架在類中包裝窗口,因此當類對象從父類移動到另一個父類(例如,VCL具有CM_CONTROLLISTCHANGING,CM_CONTROLLISTCHANGECM_CONTROLCHANGE通知)時,它們會發出自己的通知。

您能通過檢測父窗口中的變化來提供更多關於您想要完成的內容的信息嗎?

+0

我的窗口在一個插件中,它被動態地插入主機程序的窗口層次結構中,我需要檢測它何時在主機層次結構中的不同位置之間移動。 – solsberg 2010-10-04 21:58:39

+0

然後我建議你記錄你的插件窗口實際收到的消息,然後根據你的需要選擇最合適的消息。 – 2010-10-04 23:34:27

+0

是的,這就是我現在正在做的事情,當我收到一個WM_WINDOWPOSCHANGED消息並與前一個父句柄 – solsberg 2010-10-05 12:51:45

0

Sort-of ...在使用Windows之間的消息傳遞之前,我已經完成了此操作,並且有一個線程可以在它們之間進行監聽。請記住,你不想修改任何線程的UI,然後創建它的那個...

這是父窗口的一些示例代碼,通過它的一個子窗口獲得變化的通知。同樣的原則適用於你正在談論的事情。父母的Windows在兒童開放的時候並不是真的在抽取信息,(當然,但我忘記當時正在經歷的是什麼)......從我必須做這樣的事情已經有10年了......但下面的代碼是爲具有網格的父窗口和打開的「添加/編輯」窗口而設計的,當您添加或編輯項目時,它將更新「模態編輯」窗口後面的父級網格。這是在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 Windows HWND發送消息以使其更新。 。)

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

然後,這一切都被設置成當用戶選擇「NEXT」對話框中,而不是確定,或取消運動...

_beginthread(GridUpdateThread, NULL, this); 

那麼,希望這將有助於你有些,或給你一些想法...

+0

比較時,調用GetParent()有用的信息,但我認爲你正在回答一個不同的問題。 – 2010-10-04 22:29:00

+0

在我的確切例子中,是的。但是,我所做的一點是他可以用來監視事物的一種方式,或者可以使用SetParent()的覆蓋或某種性質。示例的要點是展示如何使用線程和自定義消息在兩個窗口之間進行對話。我認爲他可以用我提到的方法做他想做的事情......沒有任何內容可以爲他做到...... – LarryF 2010-10-06 03:47:25