![]() |
Issue with getting a screenshot in Win 10 from within TIdHTTPServer GET handler - Printable Version +- Atozed Forums (https://www.atozed.com/forums) +-- Forum: Indy (https://www.atozed.com/forums/forum-8.html) +--- Forum: Indy General Discussion (https://www.atozed.com/forums/forum-9.html) +--- Thread: Issue with getting a screenshot in Win 10 from within TIdHTTPServer GET handler (/thread-2782.html) |
Issue with getting a screenshot in Win 10 from within TIdHTTPServer GET handler - Ahmed Sayed - 06-29-2022 Hi, I am having a weird issue regarding taking a desktop screenshot and sending it via http GET request on Windows 10. This works fine on windows 7 but I don't know for some reason it does not work the same on windows 10. It always produces a white image. When I use the same function outside the GET event it works fine on Win10, at first I thought it did not work because of the function is called inside a separate thread but I tested it with another thread call and it worked just fine but does not work with Indy HTTP GET thread. I don't know if it is an Indy's issue because I tried everything and nothing works. Here is the code: Code: TStream* GetDesktopScreenShotStream(float Width, float Height) Code: void TForm1::SaveScreen() What am I doing wrong? Any help will be appreciated. Thanks in advance RE: Issue with getting a screenshot in Win 10 from within TIdHTTPServer GET handler - rlebeau - 06-30-2022 (06-29-2022, 04:31 PM)Ahmed Sayed Wrote: I am having a weird issue regarding taking a desktop screenshot and sending it via http GET request on Windows 10. This works fine on windows 7 but I don't know for some reason it does not work the same on windows 10. It always produces a white image. This is not a Windows issue, or even an Indy issue. It is a VCL threading issue, and one that has existed for a very long time, so you probably just didn't notice it before due to the timing of your code. In a nutshell, the VCL maintains a global cache of HDC handles for the Vcl::Graphics::TBitmapCanvas and Vcl::Controls::TControlCanvas classes. In a GUI project, the main message loop will frequently (ie, after every message processed!) free unused HDC handles in that cache. Which means, in your case, that any TBitmap object you are using outside of the main UI thread risks having its GDI resources rip out from behind its back unexpectedly. That is why you are getting trashed images. To avoid this, you MUST call the Canvas->Lock() and Canvas->Unlock() methods of the TBitmap when it is used in a worker thread. The main UI thread will not free resources for locked canvases. (06-29-2022, 04:31 PM)Ahmed Sayed Wrote: at first I thought it did not work because of the function is called inside a separate thread That is exactly why it is not working correctly. (06-29-2022, 04:31 PM)Ahmed Sayed Wrote: but I tested it with another thread call and it worked just fine Only due to a fluke in timing. When you click on your button to create the thread, and then the button handler returns control back to the main message loop, the main thread frees unlocked canvas resources, which is likely occurring either before or after your thread is using them, so your test does not get invalidated. (06-29-2022, 04:31 PM)Ahmed Sayed Wrote: What am I doing wrong? You are not locking access to the TBitmap::Canvas to protect its resources. Try something more like this: Code: struct HDC_deleter Code: void TForm1::SaveScreen() The alternative is to simply not use TBitmap in a worker thread to begin with. Prepare and save the BMP data using direct Win32 API calls only, or maybe use GDI+ instead, or find a 3rd-party graphics library that is thread-safe. RE: Issue with getting a screenshot in Win 10 from within TIdHTTPServer GET handler - Ahmed Sayed - 07-04-2022 Thanks for the help. I tried your solution and it produces the same issue white image. Maybe I did not provide more info about the issue but this only happened when I used my app on a remote machine on the same network that runs Windows 10. At first I thought it was a windows issue then an Indy one. But It is not even a VCL issue because I tried the same app but with FMX and it did the same thing. Turns out to be that when I used RDP to connect to the remote machine. Whenever I minimized the remote window it is like that the desktop is gone on the remote machine, so I had to keep the RDP window on top while running the server on that machine and testing the client on my machine. ![]() Sure it was a mere coincidence that made me discover this was the problem. And again thanks |