| 113 | |
| 114 | |
| 115 | Script::~Script() |
| 116 | { |
| 117 | // MSDN: "Before terminating, an application must call the UnhookWindowsHookEx function to free |
| 118 | // system resources associated with the hook." |
| 119 | RemoveAllHooks(); |
| 120 | if (mNIC.hWnd) // Tray icon is installed. |
| 121 | Shell_NotifyIcon(NIM_DELETE, &mNIC); // Remove it. |
| 122 | // Only after the above do we get rid of the icon: |
| 123 | if (mCustomIcon) // A custom icon was installed |
| 124 | DestroyIcon(mCustomIcon); |
| 125 | // Destroy any Progress/SplashImage windows that haven't already been destroyed. This is necessary |
| 126 | // because sometimes these windows aren't owned by the main window: |
| 127 | int i; |
| 128 | for (i = 0; i < MAX_PROGRESS_WINDOWS; ++i) |
| 129 | { |
| 130 | if (g_Progress[i].hwnd && IsWindow(g_Progress[i].hwnd)) |
| 131 | DestroyWindow(g_Progress[i].hwnd); |
| 132 | if (g_Progress[i].hfont1) // Destroy font only after destroying the window that uses it. |
| 133 | DeleteObject(g_Progress[i].hfont1); |
| 134 | if (g_Progress[i].hfont2) // Destroy font only after destroying the window that uses it. |
| 135 | DeleteObject(g_Progress[i].hfont2); |
| 136 | if (g_Progress[i].hbrush) |
| 137 | DeleteObject(g_Progress[i].hbrush); |
| 138 | } |
| 139 | for (i = 0; i < MAX_SPLASHIMAGE_WINDOWS; ++i) |
| 140 | { |
| 141 | if (g_SplashImage[i].pic) |
| 142 | g_SplashImage[i].pic->Release(); |
| 143 | if (g_SplashImage[i].hwnd && IsWindow(g_SplashImage[i].hwnd)) |
| 144 | DestroyWindow(g_SplashImage[i].hwnd); |
| 145 | if (g_SplashImage[i].hfont1) // Destroy font only after destroying the window that uses it. |
| 146 | DeleteObject(g_SplashImage[i].hfont1); |
| 147 | if (g_SplashImage[i].hfont2) // Destroy font only after destroying the window that uses it. |
| 148 | DeleteObject(g_SplashImage[i].hfont2); |
| 149 | if (g_SplashImage[i].hbrush) |
| 150 | DeleteObject(g_SplashImage[i].hbrush); |
| 151 | } |
| 152 | |
| 153 | // It is safer/easier to destroy the GUI windows prior to the menus (especially the menu bars). |
| 154 | // This is because one GUI window might get destroyed and take with it a menu bar that is still |
| 155 | // in use by an existing GUI window. GuiType::Destroy() adheres to this philosophy by detaching |
| 156 | // its menu bar prior to destroying its window: |
| 157 | for (i = 0; i < MAX_GUI_WINDOWS; ++i) |
| 158 | GuiType::Destroy(i); // Static method to avoid problems with object destroying itself. |
| 159 | for (i = 0; i < GuiType::sFontCount; ++i) // Now that GUI windows are gone, delete all GUI fonts. |
| 160 | if (GuiType::sFont[i].hfont) |
| 161 | DeleteObject(GuiType::sFont[i].hfont); |
| 162 | // The above might attempt to delete an HFONT from GetStockObject(DEFAULT_GUI_FONT), etc. |
| 163 | // But that should be harmless: |
| 164 | // MSDN: "It is not necessary (but it is not harmful) to delete stock objects by calling DeleteObject." |
| 165 | |
| 166 | // Since they're not associated with a window, we must free the resources for all popup menus. |
| 167 | // Update: Even if a menu is being used as a GUI window's menu bar, see note above for why menu |
| 168 | // destruction is done AFTER the GUI windows are destroyed: |
| 169 | UserMenu *menu_to_delete; |
| 170 | for (UserMenu *m = mFirstMenu; m;) |
| 171 | { |
| 172 | menu_to_delete = m; |
nothing calls this directly
no test coverage detected