diff --git a/Import/GacUI.cpp b/Import/GacUI.cpp index 2f87736c..7cf4cd54 100644 --- a/Import/GacUI.cpp +++ b/Import/GacUI.cpp @@ -6411,7 +6411,7 @@ GuiControlHost control=control->GetParent(); } } - return 0; + return nullptr; } void GuiControlHost::MoveIntoTooltipControl(GuiControl* tooltipControl, Point location) @@ -6547,7 +6547,15 @@ GuiControlHost void GuiControlHost::Destroying() { WindowDestroying.Execute(GetNotifyEventArguments()); - SetNativeWindow(0); + calledDestroyed = true; + if (deleteWhenDestroyed) + { + GetApplication()->InvokeInMainThread(this, [=]() + { + delete this; + }); + } + SetNativeWindow(nullptr); } void GuiControlHost::UpdateClientSizeAfterRendering(Size clientSize) @@ -6580,6 +6588,20 @@ GuiControlHost delete host; } + void GuiControlHost::DeleteAfterProcessingAllEvents() + { + auto window = host->GetNativeWindow(); + if (calledDestroyed || !window) + { + delete this; + } + else + { + deleteWhenDestroyed = true; + GetCurrentController()->WindowService()->DestroyNativeWindow(window); + } + } + compositions::GuiGraphicsHost* GuiControlHost::GetGraphicsHost() { return host; @@ -6902,17 +6924,17 @@ GuiControlHost void GuiControlHost::Close() { - INativeWindow* window=host->GetNativeWindow(); - if(window) + if (auto window = host->GetNativeWindow()) { - if(GetCurrentController()->WindowService()->GetMainWindow()!=window) + auto mainWindow = GetCurrentController()->WindowService()->GetMainWindow(); + if (mainWindow == window) { - window->Hide(false); + SetNativeWindow(nullptr); + GetCurrentController()->WindowService()->DestroyNativeWindow(window); } else { - SetNativeWindow(0); - GetCurrentController()->WindowService()->DestroyNativeWindow(window); + window->Hide(false); } } } @@ -7054,7 +7076,7 @@ GuiWindow INativeWindow* window=host->GetNativeWindow(); if(window) { - SetNativeWindow(0); + SetNativeWindow(nullptr); GetCurrentController()->WindowService()->DestroyNativeWindow(window); } } @@ -7153,7 +7175,7 @@ GuiWindow ShowModal(owner, [=]() { callback(); - delete this; + DeleteAfterProcessingAllEvents(); }); } @@ -8599,8 +8621,15 @@ Helper Functions void SafeDeleteControl(controls::GuiControl* value) { - NotifyFinalizeInstance(value); - SafeDeleteControlInternal(value); + if (auto controlHost = dynamic_cast(value)) + { + controlHost->DeleteAfterProcessingAllEvents(); + } + else + { + NotifyFinalizeInstance(value); + SafeDeleteControlInternal(value); + } } void SafeDeleteComposition(GuiGraphicsComposition* value) diff --git a/Import/GacUI.h b/Import/GacUI.h index 7dd2530d..a356d5f0 100644 --- a/Import/GacUI.h +++ b/Import/GacUI.h @@ -2218,28 +2218,28 @@ Native Window Services /// Create a window. /// /// The created window. - virtual INativeWindow* CreateNativeWindow()=0; + virtual INativeWindow* CreateNativeWindow() = 0; /// /// Destroy a window. /// /// The window to destroy. - virtual void DestroyNativeWindow(INativeWindow* window)=0; + virtual void DestroyNativeWindow(INativeWindow* window) = 0; /// /// Get the main window. /// /// The main window. - virtual INativeWindow* GetMainWindow()=0; + virtual INativeWindow* GetMainWindow() = 0; /// /// Get the window that under a specified position in screen space. /// /// The window that under a specified position in screen space. /// The specified position in screen space. - virtual INativeWindow* GetWindow(Point location)=0; + virtual INativeWindow* GetWindow(Point location) = 0; /// /// Make the specified window a main window, show that window, and wait until the windows is closed. /// /// The specified window. - virtual void Run(INativeWindow* window)=0; + virtual void Run(INativeWindow* window) = 0; }; /// @@ -11002,14 +11002,17 @@ Control Host virtual void OnNativeWindowChanged(); virtual void OnVisualStatusChanged(); protected: - static const vint TooltipDelayOpenTime=500; - static const vint TooltipDelayCloseTime=500; - static const vint TooltipDelayLifeTime=5000; + static const vint TooltipDelayOpenTime = 500; + static const vint TooltipDelayCloseTime = 500; + static const vint TooltipDelayLifeTime = 5000; Ptr tooltipOpenDelay; Ptr tooltipCloseDelay; Point tooltipLocation; + bool calledDestroyed = false; + bool deleteWhenDestroyed = false; + controls::GuiControlHost* GetControlHostForInstance()override; GuiControl* GetTooltipOwner(Point location); void MoveIntoTooltipControl(GuiControl* tooltipControl, Point location); @@ -11051,6 +11054,9 @@ Control Host /// Window destroying event. compositions::GuiNotifyEvent WindowDestroying; + /// Delete this control host after processing all events. + void DeleteAfterProcessingAllEvents(); + /// Get the internal object to host the window content. /// The internal object to host the window content. compositions::GuiGraphicsHost* GetGraphicsHost(); diff --git a/Import/GacUIReflection.cpp b/Import/GacUIReflection.cpp index 27f94386..e88e4f93 100644 --- a/Import/GacUIReflection.cpp +++ b/Import/GacUIReflection.cpp @@ -2166,6 +2166,7 @@ Type Declaration (Class) CLASS_MEMBER_PROPERTY_FAST(ShortcutKeyManager) CLASS_MEMBER_PROPERTY_READONLY_FAST(RelatedScreen) + CLASS_MEMBER_METHOD(DeleteAfterProcessingAllEvents, NO_PARAMETER) CLASS_MEMBER_METHOD(ForceCalculateSizeImmediately, NO_PARAMETER) CLASS_MEMBER_METHOD(GetFocused, NO_PARAMETER) CLASS_MEMBER_METHOD(SetFocused, NO_PARAMETER) diff --git a/Import/GacUIWindows.cpp b/Import/GacUIWindows.cpp index 8b7fbb16..97d142ec 100644 --- a/Import/GacUIWindows.cpp +++ b/Import/GacUIWindows.cpp @@ -13301,30 +13301,22 @@ WindowsForm protected: HWND handle; WString title; - WindowsCursor* cursor; + WindowsCursor* cursor = nullptr; Point caretPoint; - WindowsForm* parentWindow; - bool alwaysPassFocusToParent; + WindowsForm* parentWindow = nullptr; + bool alwaysPassFocusToParent = false; List listeners; - vint mouseLastX; - vint mouseLastY; - vint mouseHoving; - Interface* graphicsHandler; - bool customFrameMode; + vint mouseLastX = -1; + vint mouseLastY = -1; + bool mouseHoving = false; + Interface* graphicsHandler = nullptr; + bool customFrameMode = false; List> messageHandlers; - bool supressingAlt; + bool supressingAlt = false; + Ptr flagDisposed = new bool(false); public: WindowsForm(HWND parent, WString className, HINSTANCE hInstance) - :cursor(0) - ,parentWindow(0) - ,alwaysPassFocusToParent(false) - ,mouseLastX(-1) - ,mouseLastY(-1) - ,mouseHoving(false) - ,graphicsHandler(0) - ,customFrameMode(false) - ,supressingAlt(false) { DWORD exStyle = WS_EX_APPWINDOW | WS_EX_CONTROLPARENT; DWORD style = WS_BORDER | WS_CAPTION | WS_SIZEBOX | WS_SYSMENU | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; @@ -13333,12 +13325,13 @@ WindowsForm ~WindowsForm() { + *flagDisposed.Obj() = true; List copiedListeners; CopyFrom(copiedListeners, listeners); - for(vint i=0;iDestroyed(); } @@ -13356,11 +13349,14 @@ WindowsForm bool HandleMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result) { +#define CHECK_DISPOSED if (*flag.Obj()) return skip + auto flag = flagDisposed; bool skip = false; { FOREACH(Ptr, handler, messageHandlers) { handler->BeforeHandle(hwnd, uMsg, wParam, lParam, skip); + CHECK_DISPOSED; } if (skip) { @@ -13368,14 +13364,17 @@ WindowsForm } } skip = HandleMessageInternal(hwnd, uMsg, wParam, lParam, result); + CHECK_DISPOSED; if (GetWindowsFormFromHandle(hwnd)) { FOREACH(Ptr, handler, messageHandlers) { handler->AfterHandle(hwnd, uMsg, wParam, lParam, skip, result); + CHECK_DISPOSED; } } return skip; +#undef CHECK_DISPOSED } HWND GetWindowHandle()override @@ -13824,6 +13823,7 @@ WindowsController Dictionary windows; INativeWindow* mainWindow; HWND mainWindowHandle; + vint handleMessageLevelCounter = 0; WindowsCallbackService callbackService; WindowsResourceService resourceService; @@ -13868,51 +13868,59 @@ WindowsController bool HandleMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result) { bool skipDefaultProcedure=false; - vint index=windows.Keys().IndexOf(hwnd); - if(index!=-1) + handleMessageLevelCounter++; { - WindowsForm* window=windows.Values().Get(index); - skipDefaultProcedure=window->HandleMessage(hwnd, uMsg, wParam, lParam, result); - switch(uMsg) + vint index = windows.Keys().IndexOf(hwnd); + if (index != -1) { - case WM_CLOSE: - if(!skipDefaultProcedure) + WindowsForm* window = windows.Values().Get(index); + skipDefaultProcedure = window->HandleMessage(hwnd, uMsg, wParam, lParam, result); + switch (uMsg) { - ShowWindow(window->GetWindowHandle(), SW_HIDE); - if(window!=mainWindow) + case WM_CLOSE: + if (!skipDefaultProcedure) { - skipDefaultProcedure=true; + ShowWindow(window->GetWindowHandle(), SW_HIDE); + if (window != mainWindow) + { + skipDefaultProcedure = true; + } + } + break; + case WM_DESTROY: + DestroyNativeWindow(window); + break; + } + } + } + { + if (hwnd == mainWindowHandle && uMsg == WM_DESTROY) + { + for (vint i = 0; i < windows.Count(); i++) + { + if (windows.Values().Get(i)->IsVisible()) + { + windows.Values().Get(i)->Hide(true); } } - break; - case WM_DESTROY: - DestroyNativeWindow(window); - break; - } - } - - if(hwnd==mainWindowHandle && uMsg==WM_DESTROY) - { - for(vint i=0;iIsVisible()) + while (windows.Count()) { - windows.Values().Get(i)->Hide(true); + DestroyNativeWindow(windows.Values().Get(0)); } + PostQuitMessage(0); } - while(windows.Count()) - { - DestroyNativeWindow(windows.Values().Get(0)); - } - PostQuitMessage(0); } - asyncService.ExecuteAsyncTasks(); + handleMessageLevelCounter--; + if (handleMessageLevelCounter == 0) + { + asyncService.ExecuteAsyncTasks(); + } return skipDefaultProcedure; } //======================================================================= - INativeWindow* CreateNativeWindow() + INativeWindow* CreateNativeWindow()override { WindowsForm* window=new WindowsForm(godWindow, windowClass.GetName(), hInstance); windows.Add(window->GetWindowHandle(), window); @@ -13921,7 +13929,7 @@ WindowsController return window; } - void DestroyNativeWindow(INativeWindow* window) + void DestroyNativeWindow(INativeWindow* window)override { WindowsForm* windowsForm=dynamic_cast(window); windowsForm->InvokeDestroying(); @@ -13933,12 +13941,12 @@ WindowsController } } - INativeWindow* GetMainWindow() + INativeWindow* GetMainWindow()override { return mainWindow; } - void Run(INativeWindow* window) + void Run(INativeWindow* window)override { mainWindow=window; mainWindowHandle=GetWindowsForm(window)->GetWindowHandle(); @@ -13952,7 +13960,7 @@ WindowsController } } - INativeWindow* GetWindow(Point location) + INativeWindow* GetWindow(Point location)override { POINT p; p.x=(int)location.x; diff --git a/Tutorial/GacUI_Controls/AddressBook/UI/Resource.xml b/Tutorial/GacUI_Controls/AddressBook/UI/Resource.xml index 5a7ed528..4a3cc8e6 100644 --- a/Tutorial/GacUI_Controls/AddressBook/UI/Resource.xml +++ b/Tutorial/GacUI_Controls/AddressBook/UI/Resource.xml @@ -305,7 +305,7 @@