dwmkerr / sharpshell

SharpShell makes it easy to create Windows Shell Extensions using the .NET Framework.
MIT License
1.49k stars 261 forks source link

Preview handler steals focus from Explorer window #403

Open Jdbye opened 3 months ago

Jdbye commented 3 months ago

Version of SharpShell used: 2.7.2

Related type(s) of SharpShell-Server: Any

Whenever the preview handler is called (so any time an applicable file is selected) the preview handler itself steals focus. That has the effect of making it difficult to select files and use keyboard shortcuts like Ctrl+C, and I can't jump to a file in Explorer by typing in the first couple letters (which I do a lot), as soon as I type the first letter and it lands on one of the files the preview handler applies to, focus is taken away from Explorer and the preview handler receives the rest of the key inputs.

This seems likely to be related to how SharpShell is creating the borderless window. Obviously normal behavior when you open an application is for the window to open on top of your other windows and receive focus. But in this case, we don't want that. We want the user control to act like part of the Explorer window.

My preview handler control contains a PictureBox, and a RichTextBox that displays additional metadata. I don't know if the RichTextBox could be causing the issue, since it's a control that normally accepts input (it is set to ReadOnly though), but I doubt it, since the explorer window visibly loses focus, as the title bar changes color. I did have a look at the properties on the control to see if there was anything that could affect this behavior. On forms, you have a bunch of options that affect how the form is displayed when it is loaded, but I couldn't find any settings like that on the PreviewHandlerControl.

Side note: The shell extension works on one of my PCs but not the other, Explorer just says "This file can't be previewed because of an error in Preview Handler". It's probably throwing an exception but all my code is already in try catch blocks and I'm finding it very hard to debug the issue. I've never worked with shell extensions before, obviously I can't just attach a debugger, and I tried to write uncaught exceptions to a log file using an uncaught exception handler but there is nothing written, so the exception might even be happening during initialization. Nothing is written to the SharpShell log file (using SharpShell Easy Log) either. What is weird is that It works perfectly fine in Server Manager (using the test shell). What am I missing? Are there any other ways to debug a shell extension? Edit: The logging in SharpShell Easy Log does work as it logs things when I use the test shell. But using explorer itself no logs are produced. Edit2: I made it work on my second PC, I tried the normal release build of my app instead of the publish build (since on my other PC I'm using the debug build so I thought maybe the publish build was the issue), it worked, then I switched back to the publish build, and it still works. I have no idea why it wasn't working before, but at least it works now. Honestly, the preview handler has been a bit hit and miss even on the PC it worked on, since sometimes it would just decide to stop working out of the blue and require a reboot. The context menu handler has now decided to not work, and that one normally works. Weird. Edit3: That only lasted until a reboot. Seems like the release build fixed something temporarily and (presumably) prevhost.exe kept whatever it was in memory, allowing the publish build to work. As far as I can tell, it might be SharpShell.dll itself. I used ILRepack so that the shell extension DLL wouldn't need to rely on a bunch of extra files. That isn't unique to the publish build. But, the release build has a copy of SharpShell.dll in the same directory (because the application that the shell extension goes with uses SharpShell.dll for installing/uninstalling the shell extension, and the application itself doesn't use ILRepack) That was just a hunch, so I copied SharpShell.dll to the folder with the publish build, rebooted, and the shell extension started working again. Seems like I've solved it. My best guess, SharpShellNativeBridge is embedded into that DLL and it isn't included, or isn't able to load from the ILRepack embedded assembly (being native code). Would make sense.

DanielBrownAU commented 3 months ago

Attach it to explore.exe and set your breakpoints

From: Jdbaii @.> Sent: Monday, May 13, 2024 6:49 PM To: dwmkerr/sharpshell @.> Cc: Subscribed @.***> Subject: [dwmkerr/sharpshell] Preview handler steals focus from Explorer window (Issue #403)

Version of SharpShell used: 2.7.2

Related type(s) of SharpShell-Server: Any

Whenever the preview handler is called (so any time an applicable file is selected) the preview handler itself steals focus. That has the effect of making it difficult to select files and use keyboard shortcuts like Ctrl+C, and I can't jump to a file in Explorer by typing in the first couple letters (which I do a lot), as soon as I type the first letter and it lands on one of the files the preview handler applies to, focus is taken away from Explorer and the preview handler receives the rest of the key inputs.

This seems likely to be related to how SharpShell is creating the borderless window. Obviously normal behavior when you open an application is for the window to open on top of your other windows and receive focus. But in this case, we don't want that. We want the user control to act like part of the Explorer window.

My preview handler control contains a PictureBox, and a RichTextBox that displays additional metadata. I don't know if the RichTextBox could be causing the issue, since it's a control that normally accepts input (it is set to ReadOnly though), but I doubt it, since the explorer window visibly loses focus, as the title bar changes color. I did have a look at the properties on the control to see if there was anything that could affect this behavior. On forms, you have a bunch of options that affect how the form is displayed when it is loaded, but I couldn't find any settings like that on the PreviewHandlerControl.

Side note: The shell extension works on one of my PCs but not the other, it's probably throwing an exception but I'm finding it very hard to debug the issue. I've never worked with shell extensions before, obviously I can't just attach a debugger, and I tried to write uncaught exceptions to a log file using an uncaught exception handler but there is nothing written, so the exception might even be happening during initialization. Nothing is written to the SharpShell log file (using SharpShell Easy Log) either. What am I missing? Are there any other ways to debug a shell extension?

— Reply to this email directly, view it on GitHubhttps://github.com/dwmkerr/sharpshell/issues/403, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ADFMAEMKXBDVN5YIO3UXXQ3ZCCAR3AVCNFSM6AAAAABHT2AZDSVHI2DSMVQWIX3LMV43ASLTON2WKOZSGI4TEMRWHE3DCMA. You are receiving this because you are subscribed to this thread.Message ID: @.***>

5cutters commented 3 months ago

Could it be as simple as setting the richtextbox TabStop property to false?. Just a guess , not had a focus issue with a preview handler but only used them with picturebox and label controls.

Jdbye commented 3 months ago

Could it be as simple as setting the richtextbox TabStop property to false?. Just a guess , not had a focus issue with a preview handler but only used them with picturebox and label controls.

No dice, the window still loses focus. I wasn't expecting much, so that's not a surprise.

Jdbye commented 3 months ago

On my laptop, this behavior with the Explorer window losing focus doesn't happen. Only seems to happen on my desktop for some strange reason. I also seem to remember it wasn't always like that, but started doing it at some point and has been doing it since.

Jdbye commented 3 months ago

I solved the issue, though not without drawbacks.

cp.ExStyle |= 0x08000000; // Turn on WS_EX_NOACTIVATE

Adding this line to CreateParams in SharpShell\SharpShell\SharpPreviewHandler\PreviewHandlerHost.cs solves the issue. The drawback is that I can't select text in the RichTextBox anymore. However, the preview box can still be interacted with in other ways. I can even scroll the scrollbar of the RichTextBox (though it is a bit glitched since the scrollbar position doesn't visually update until I let go of the mouse button) For most uses of a preview handler, this might actually be preferrable. Since clicking inside the preview box won't take away focus from the Explorer window anymore. It acts more like an extension of the Explorer window rather than a separate window. I simply implemented another way to copy text, so this problem is fully solved as far as I'm concerned.

Not sure why it started behaving like this on my desktop in the first place. Since it doesn't do it on my laptop, and it didn't originally do it on my desktop as far as I can remember, but randomly started doing it at some point. I guess I'll never know.