mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 03:37:59 +01:00
[PreviewPane] Fix form positioning issues (#34035)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This PR aims to fix some positioning issues of the form used as preview
handler.
It fixes the following issues:
1. The floating window, detached from Explorer that sometimes appears:
#33491 #27475 #24985
2. The **CoreWebView2 members cannot be accessed after the WebView2
control is disposed** crash: #27276
3. `PowerToys.*.PreviewHandler.exe` process leak
### Repro steps for issue 1
- Navigate through files in a folder invoking their preview handler
- Minimize/Restore Explorer quickly (spam WIN+D usually works)
- 2 weird issues happen:
- Some `PowerToys.*.PreviewHandler.exe` processes are leaked
- Some `PowerToys.*.PreviewHandler.exe` are started with a `NULL` `HWND`

This happens because
[IPreviewHandler::DoPreview](https://learn.microsoft.com/windows/win32/api/shobjidl_core/nf-shobjidl_core-ipreviewhandler-dopreview)
is called multiple times and sometimes before calling
[IPreviewHandler::SetWindow](https://learn.microsoft.com/windows/win32/api/shobjidl_core/nf-shobjidl_core-ipreviewhandler-setwindow).
When the managed previewer try to set the parent of the form to the
`NULL` `HWND`, the desktop window is used instead, resulting in the
floating preview window being displayed.
Reference:
https://learn.microsoft.com/windows/win32/api/winuser/nf-winuser-setparent#parameters
5d77874382/src/modules/previewpane/common/controls/FormHandlerControl.cs (L136)
### Repro steps for issue 2
- Preview a file
- Restart `explorer.exe` process
- Make sure `PowerToys.*.PreviewHandler.exe` is leaked and still running
- Preview the same file again
- Preview is displayed (another process is launched)
- Minimize Explorer
What happens here is that the form of the old process have an invalid
`HWND` as parent but receive the `SetRect` for some reason.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] **Closes:** #33491 #27475 #24985 #27276
- [ ] **Communication:** I've discussed this with core contributors
already. If work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end user facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx
<!-- Provide a more detailed description of the PR, other things fixed
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
- Don't start preview pane process when `HWND` is `NULL`
- Terminate the preview pane process when setting parent fails
- Prevent leaking processes closing them when a new preview is requested
- Fixed an issue where PDF and SVG previews weren't updated after
restoring Explorer
- Added some error handling in the `UpdateWindowBounds` method of the
managed preview
- Terminate the preview pane when the `SetRect` event is received but
the parent `HWND` has become invalid
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
- Manually tested all preview panes also using multiple Explorer windows
- Validated that when Explorer is minimized/restored the preview is
updated
- Tested the preview pane resize
- Validated that no window, no taskbar icon and no errors appear on both
repro steps
This commit is contained in:
committed by
GitHub
parent
761e18a245
commit
3798a101a6
@@ -36,15 +36,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Gcode
|
|||||||
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
||||||
|
|
||||||
_previewHandlerControl = new GcodePreviewHandlerControl();
|
_previewHandlerControl = new GcodePreviewHandlerControl();
|
||||||
_previewHandlerControl.SetWindow(hwnd, s);
|
|
||||||
|
if (!_previewHandlerControl.SetWindow(hwnd, s))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_previewHandlerControl.DoPreview(filePath);
|
_previewHandlerControl.DoPreview(filePath);
|
||||||
|
|
||||||
NativeEventWaiter.WaitForEventLoop(
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
Constants.GcodePreviewResizeEvent(),
|
Constants.GcodePreviewResizeEvent(),
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
Rectangle s = default(Rectangle);
|
Rectangle s = default;
|
||||||
_previewHandlerControl.SetRect(s);
|
if (!_previewHandlerControl.SetRect(s))
|
||||||
|
{
|
||||||
|
// When the parent HWND became invalid, the application won't respond to Application.Exit().
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Dispatcher.CurrentDispatcher,
|
Dispatcher.CurrentDispatcher,
|
||||||
_tokenSource.Token);
|
_tokenSource.Token);
|
||||||
|
|||||||
@@ -159,9 +159,9 @@ IFACEMETHODIMP GcodePreviewHandler::DoPreview()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
|
if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
|
||||||
{
|
{
|
||||||
// Postponing Start GcodePreviewHandler.exe, position not yet initialized. preview will be done after initialisation
|
// Postponing Start GcodePreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
Logger::info(L"Starting GcodePreviewHandler.exe");
|
Logger::info(L"Starting GcodePreviewHandler.exe");
|
||||||
@@ -189,6 +189,13 @@ IFACEMETHODIMP GcodePreviewHandler::DoPreview()
|
|||||||
sei.lpParameters = cmdLine.c_str();
|
sei.lpParameters = cmdLine.c_str();
|
||||||
sei.nShow = SW_SHOWDEFAULT;
|
sei.nShow = SW_SHOWDEFAULT;
|
||||||
ShellExecuteEx(&sei);
|
ShellExecuteEx(&sei);
|
||||||
|
|
||||||
|
// Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
|
||||||
|
if (m_process)
|
||||||
|
{
|
||||||
|
TerminateProcess(m_process, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_process = sei.hProcess;
|
m_process = sei.hProcess;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|||||||
@@ -36,15 +36,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Markdown
|
|||||||
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
||||||
|
|
||||||
_previewHandlerControl = new MarkdownPreviewHandlerControl();
|
_previewHandlerControl = new MarkdownPreviewHandlerControl();
|
||||||
_previewHandlerControl.SetWindow(hwnd, s);
|
|
||||||
|
if (!_previewHandlerControl.SetWindow(hwnd, s))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_previewHandlerControl.DoPreview(filePath);
|
_previewHandlerControl.DoPreview(filePath);
|
||||||
|
|
||||||
NativeEventWaiter.WaitForEventLoop(
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
Constants.MarkdownPreviewResizeEvent(),
|
Constants.MarkdownPreviewResizeEvent(),
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
Rectangle s = default(Rectangle);
|
Rectangle s = default;
|
||||||
_previewHandlerControl.SetRect(s);
|
if (!_previewHandlerControl.SetRect(s))
|
||||||
|
{
|
||||||
|
// When the parent HWND became invalid, the application won't respond to Application.Exit().
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Dispatcher.CurrentDispatcher,
|
Dispatcher.CurrentDispatcher,
|
||||||
_tokenSource.Token);
|
_tokenSource.Token);
|
||||||
|
|||||||
@@ -160,9 +160,9 @@ IFACEMETHODIMP MarkdownPreviewHandler::DoPreview()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
|
if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
|
||||||
{
|
{
|
||||||
// Postponing Start MarkdownPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
|
// Postponing Start MarkdownPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
Logger::info(L"Starting MarkdownPreviewHandler.exe");
|
Logger::info(L"Starting MarkdownPreviewHandler.exe");
|
||||||
@@ -190,6 +190,13 @@ IFACEMETHODIMP MarkdownPreviewHandler::DoPreview()
|
|||||||
sei.lpParameters = cmdLine.c_str();
|
sei.lpParameters = cmdLine.c_str();
|
||||||
sei.nShow = SW_SHOWDEFAULT;
|
sei.nShow = SW_SHOWDEFAULT;
|
||||||
ShellExecuteEx(&sei);
|
ShellExecuteEx(&sei);
|
||||||
|
|
||||||
|
// Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
|
||||||
|
if (m_process)
|
||||||
|
{
|
||||||
|
TerminateProcess(m_process, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_process = sei.hProcess;
|
m_process = sei.hProcess;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|||||||
@@ -39,15 +39,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Monaco
|
|||||||
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
||||||
|
|
||||||
_previewHandlerControl = new MonacoPreviewHandlerControl();
|
_previewHandlerControl = new MonacoPreviewHandlerControl();
|
||||||
_previewHandlerControl.SetWindow(hwnd, s);
|
|
||||||
|
if (!_previewHandlerControl.SetWindow(hwnd, s))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_previewHandlerControl.DoPreview(filePath);
|
_previewHandlerControl.DoPreview(filePath);
|
||||||
|
|
||||||
NativeEventWaiter.WaitForEventLoop(
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
Constants.DevFilesPreviewResizeEvent(),
|
Constants.DevFilesPreviewResizeEvent(),
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
Rectangle s = default(Rectangle);
|
Rectangle s = default;
|
||||||
_previewHandlerControl.SetRect(s);
|
if (!_previewHandlerControl.SetRect(s))
|
||||||
|
{
|
||||||
|
// When the parent HWND became invalid, the application won't respond to Application.Exit().
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Dispatcher.CurrentDispatcher,
|
Dispatcher.CurrentDispatcher,
|
||||||
_tokenSource.Token);
|
_tokenSource.Token);
|
||||||
|
|||||||
@@ -159,9 +159,9 @@ IFACEMETHODIMP MonacoPreviewHandler::DoPreview()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
|
if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
|
||||||
{
|
{
|
||||||
// Postponing Start MonacoPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
|
// Postponing Start MonacoPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +189,13 @@ IFACEMETHODIMP MonacoPreviewHandler::DoPreview()
|
|||||||
sei.lpParameters = cmdLine.c_str();
|
sei.lpParameters = cmdLine.c_str();
|
||||||
sei.nShow = SW_SHOWDEFAULT;
|
sei.nShow = SW_SHOWDEFAULT;
|
||||||
ShellExecuteEx(&sei);
|
ShellExecuteEx(&sei);
|
||||||
|
|
||||||
|
// Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
|
||||||
|
if (m_process)
|
||||||
|
{
|
||||||
|
TerminateProcess(m_process, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_process = sei.hProcess;
|
m_process = sei.hProcess;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|||||||
@@ -35,15 +35,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Pdf
|
|||||||
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
||||||
|
|
||||||
_previewHandlerControl = new PdfPreviewHandlerControl();
|
_previewHandlerControl = new PdfPreviewHandlerControl();
|
||||||
_previewHandlerControl.SetWindow(hwnd, s);
|
|
||||||
|
if (!_previewHandlerControl.SetWindow(hwnd, s))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_previewHandlerControl.DoPreview(filePath);
|
_previewHandlerControl.DoPreview(filePath);
|
||||||
|
|
||||||
NativeEventWaiter.WaitForEventLoop(
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
Constants.PdfPreviewResizeEvent(),
|
Constants.PdfPreviewResizeEvent(),
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
Rectangle s = default(Rectangle);
|
Rectangle s = default;
|
||||||
_previewHandlerControl.SetRect(s);
|
if (!_previewHandlerControl.SetRect(s))
|
||||||
|
{
|
||||||
|
// When the parent HWND became invalid, the application won't respond to Application.Exit().
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Dispatcher.CurrentDispatcher,
|
Dispatcher.CurrentDispatcher,
|
||||||
_tokenSource.Token);
|
_tokenSource.Token);
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ IFACEMETHODIMP PdfPreviewHandler::SetRect(const RECT* prc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_rcParent = *prc;
|
||||||
hr = S_OK;
|
hr = S_OK;
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
@@ -156,9 +157,9 @@ IFACEMETHODIMP PdfPreviewHandler::DoPreview()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
|
if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
|
||||||
{
|
{
|
||||||
// Postponing Start PdfPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
|
// Postponing Start PdfPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
Logger::info(L"Starting PdfPreviewHandler.exe");
|
Logger::info(L"Starting PdfPreviewHandler.exe");
|
||||||
@@ -186,6 +187,13 @@ IFACEMETHODIMP PdfPreviewHandler::DoPreview()
|
|||||||
sei.lpParameters = cmdLine.c_str();
|
sei.lpParameters = cmdLine.c_str();
|
||||||
sei.nShow = SW_SHOWDEFAULT;
|
sei.nShow = SW_SHOWDEFAULT;
|
||||||
ShellExecuteEx(&sei);
|
ShellExecuteEx(&sei);
|
||||||
|
|
||||||
|
// Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
|
||||||
|
if (m_process)
|
||||||
|
{
|
||||||
|
TerminateProcess(m_process, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_process = sei.hProcess;
|
m_process = sei.hProcess;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|||||||
@@ -36,15 +36,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Qoi
|
|||||||
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
||||||
|
|
||||||
_previewHandlerControl = new QoiPreviewHandlerControl();
|
_previewHandlerControl = new QoiPreviewHandlerControl();
|
||||||
_previewHandlerControl.SetWindow(hwnd, s);
|
|
||||||
|
if (!_previewHandlerControl.SetWindow(hwnd, s))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_previewHandlerControl.DoPreview(filePath);
|
_previewHandlerControl.DoPreview(filePath);
|
||||||
|
|
||||||
NativeEventWaiter.WaitForEventLoop(
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
Constants.QoiPreviewResizeEvent(),
|
Constants.QoiPreviewResizeEvent(),
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
Rectangle s = default(Rectangle);
|
Rectangle s = default;
|
||||||
_previewHandlerControl.SetRect(s);
|
if (!_previewHandlerControl.SetRect(s))
|
||||||
|
{
|
||||||
|
// When the parent HWND became invalid, the application won't respond to Application.Exit().
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Dispatcher.CurrentDispatcher,
|
Dispatcher.CurrentDispatcher,
|
||||||
_tokenSource.Token);
|
_tokenSource.Token);
|
||||||
|
|||||||
@@ -159,9 +159,9 @@ IFACEMETHODIMP QoiPreviewHandler::DoPreview()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
|
if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
|
||||||
{
|
{
|
||||||
// Postponing Start QoiPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
|
// Postponing Start QoiPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
Logger::info(L"Starting QoiPreviewHandler.exe");
|
Logger::info(L"Starting QoiPreviewHandler.exe");
|
||||||
@@ -189,6 +189,13 @@ IFACEMETHODIMP QoiPreviewHandler::DoPreview()
|
|||||||
sei.lpParameters = cmdLine.c_str();
|
sei.lpParameters = cmdLine.c_str();
|
||||||
sei.nShow = SW_SHOWDEFAULT;
|
sei.nShow = SW_SHOWDEFAULT;
|
||||||
ShellExecuteEx(&sei);
|
ShellExecuteEx(&sei);
|
||||||
|
|
||||||
|
// Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
|
||||||
|
if (m_process)
|
||||||
|
{
|
||||||
|
TerminateProcess(m_process, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_process = sei.hProcess;
|
m_process = sei.hProcess;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|||||||
@@ -36,15 +36,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg
|
|||||||
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
|
||||||
|
|
||||||
_previewHandlerControl = new SvgPreviewControl();
|
_previewHandlerControl = new SvgPreviewControl();
|
||||||
_previewHandlerControl.SetWindow(hwnd, s);
|
|
||||||
|
if (!_previewHandlerControl.SetWindow(hwnd, s))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_previewHandlerControl.DoPreview(filePath);
|
_previewHandlerControl.DoPreview(filePath);
|
||||||
|
|
||||||
NativeEventWaiter.WaitForEventLoop(
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
Constants.SvgPreviewResizeEvent(),
|
Constants.SvgPreviewResizeEvent(),
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
Rectangle s = default(Rectangle);
|
Rectangle s = default;
|
||||||
_previewHandlerControl.SetRect(s);
|
if (!_previewHandlerControl.SetRect(s))
|
||||||
|
{
|
||||||
|
// When the parent HWND became invalid, the application won't respond to Application.Exit().
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Dispatcher.CurrentDispatcher,
|
Dispatcher.CurrentDispatcher,
|
||||||
_tokenSource.Token);
|
_tokenSource.Token);
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ IFACEMETHODIMP SvgPreviewHandler::SetRect(const RECT* prc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_rcParent = *prc;
|
||||||
hr = S_OK;
|
hr = S_OK;
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
@@ -158,9 +159,9 @@ IFACEMETHODIMP SvgPreviewHandler::DoPreview()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
|
if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
|
||||||
{
|
{
|
||||||
// Postponing Start SvgPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
|
// Postponing Start SvgPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
Logger::info(L"Starting SvgPreviewHandler.exe");
|
Logger::info(L"Starting SvgPreviewHandler.exe");
|
||||||
@@ -188,6 +189,13 @@ IFACEMETHODIMP SvgPreviewHandler::DoPreview()
|
|||||||
sei.lpParameters = cmdLine.c_str();
|
sei.lpParameters = cmdLine.c_str();
|
||||||
sei.nShow = SW_SHOWDEFAULT;
|
sei.nShow = SW_SHOWDEFAULT;
|
||||||
ShellExecuteEx(&sei);
|
ShellExecuteEx(&sei);
|
||||||
|
|
||||||
|
// Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
|
||||||
|
if (m_process)
|
||||||
|
{
|
||||||
|
TerminateProcess(m_process, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_process = sei.hProcess;
|
m_process = sei.hProcess;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|||||||
@@ -37,5 +37,8 @@ namespace PreviewHandlerCommon.ComInterop
|
|||||||
[DllImport("user32.dll", SetLastError = true)]
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
public static extern bool GetClientRect(IntPtr hWnd, ref Common.ComInterlop.RECT rect);
|
public static extern bool GetClientRect(IntPtr hWnd, ref Common.ComInterlop.RECT rect);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool IsWindow(IntPtr hWnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ namespace Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void SetRect(Rectangle windowBounds)
|
public bool SetRect(Rectangle windowBounds)
|
||||||
{
|
{
|
||||||
this.UpdateWindowBounds(parentHwnd, windowBounds);
|
return this.UpdateWindowBounds(parentHwnd, windowBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -85,10 +85,10 @@ namespace Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void SetWindow(IntPtr hwnd, Rectangle rect)
|
public bool SetWindow(IntPtr hwnd, Rectangle rect)
|
||||||
{
|
{
|
||||||
this.parentHwnd = hwnd;
|
this.parentHwnd = hwnd;
|
||||||
this.UpdateWindowBounds(hwnd, rect);
|
return this.UpdateWindowBounds(hwnd, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -118,12 +118,18 @@ namespace Common
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update the Form Control window with the passed rectangle.
|
/// Update the Form Control window with the passed rectangle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateWindowBounds(IntPtr hwnd, Rectangle newBounds)
|
public bool UpdateWindowBounds(IntPtr hwnd, Rectangle newBounds)
|
||||||
{
|
{
|
||||||
|
if (hwnd == IntPtr.Zero || !NativeMethods.IsWindow(hwnd))
|
||||||
|
{
|
||||||
|
// If the HWND is IntPtr.Zero the desktop window will be used as parent.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.Disposing || this.IsDisposed)
|
if (this.Disposing || this.IsDisposed)
|
||||||
{
|
{
|
||||||
// For unclear reasons, this can be called when handling an error and the form has already been disposed.
|
// For unclear reasons, this can be called when handling an error and the form has already been disposed.
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must set the WS_CHILD style to change the form to a control within the Explorer preview pane
|
// We must set the WS_CHILD style to change the form to a control within the Explorer preview pane
|
||||||
@@ -133,7 +139,10 @@ namespace Common
|
|||||||
_ = NativeMethods.SetWindowLong(Handle, gwlStyle, windowStyle | wsChild);
|
_ = NativeMethods.SetWindowLong(Handle, gwlStyle, windowStyle | wsChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeMethods.SetParent(Handle, hwnd);
|
if (NativeMethods.SetParent(Handle, hwnd) == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (newBounds.IsEmpty)
|
if (newBounds.IsEmpty)
|
||||||
{
|
{
|
||||||
@@ -146,6 +155,8 @@ namespace Common
|
|||||||
{
|
{
|
||||||
Bounds = newBounds;
|
Bounds = newBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,14 +58,16 @@ namespace Common
|
|||||||
/// Directs the control to change the area within the parent hwnd that it draws into.
|
/// Directs the control to change the area within the parent hwnd that it draws into.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="windowBounds">Instance of Rectangle defining the area.</param>
|
/// <param name="windowBounds">Instance of Rectangle defining the area.</param>
|
||||||
void SetRect(Rectangle windowBounds);
|
/// <returns><see langword="true"/> if the operation was successful; otherwise, <see langword="false"/>.</returns>
|
||||||
|
bool SetRect(Rectangle windowBounds);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the parent window of the previewer window, as well as the area within the parent to be used for the previewer window..
|
/// Sets the parent window of the previewer window, as well as the area within the parent to be used for the previewer window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hwnd">Pointer to the parent window handle.</param>
|
/// <param name="hwnd">Pointer to the parent window handle.</param>
|
||||||
/// <param name="rect">Instance of Rectangle defining the area.</param>
|
/// <param name="rect">Instance of Rectangle defining the area.</param>
|
||||||
void SetWindow(IntPtr hwnd, Rectangle rect);
|
/// <returns><see langword="true"/> if the operation was successful; otherwise, <see langword="false"/>.</returns>
|
||||||
|
bool SetWindow(IntPtr hwnd, Rectangle rect);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called by Preview Handler to start the preview.
|
/// Called by Preview Handler to start the preview.
|
||||||
|
|||||||
Reference in New Issue
Block a user