0

I have this code to draw on Desktop's canvas:

procedure Paint;  {Pseudo code}
begin
 repeat
   DrawOnWindow();
   sleep(100);
   Application.ProcessMessages;
 until;
end;

function DrawOnWindow(Handle: HWND; X, Y: Integer; BMP : TBitmap): Boolean;
{ actual code }
var
   Canvas  : TCanvas;
   DC : HDC;
begin
 Result:= FALSE;                                                            
 Assert(Handle > 0);      // if change is possible then
 try
  DC := GetDC(Handle);    // the dc is freed after repainting
  Canvas := TCanvas.Create;    
  Canvas.Handle := DC;
  Canvas.Draw(x, y, bmp);   
  Canvas.Free;
  Result := TRUE;
  ReleaseDC(Handle,DC);
 except
 end;
end;

The drawing worked fine. But it was freezing my program and I had to use Application.ProcessMessages to 'unfreeze' it. But Application.ProcessMessages was creating its own problems.

So I moved the code in a thread. Now it works for a while (< 1 minute) then the canvas is not painted anymore (but the thread is running).

  1. Why is this happening? Am I supposed to lock that canvas?
  2. An alternative question (path) would be: Should I move the painting code back in the main app/thread and paint from a TTimer (or better, a high precision timer)?
Wouter van Nifterick
  • 23,603
  • 7
  • 78
  • 122
Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • You are supposed to pass the graphics to the main thread notifying it about the target window needs to be repainted (and flush the graphics to the window canvas when that window requests it, in the main thread). – Victoria May 31 '17 at 09:32
  • It's never going to work reliably. You can't just paint on somebody else's window from another process. For sure `TCanvas` is a mess, and trouble in a thread. Just blit the bitmap using GDI functions. Not hard. But it still won't work out for you well in the long run. You are likely to bring the other process down. – David Heffernan May 31 '17 at 09:51
  • That's right. Never paint anything from outside the main thread. Painting is done in the main thread when the window requests that (in Delphi paint in the `Paint` method). – Victoria May 31 '17 at 09:54
  • 2
    @Victoria Altar is painting on a window owned by another process, so he can't obey that rule unless he finds a way to inject code into that process which executes in its main thread. – David Heffernan May 31 '17 at 09:55
  • @David don't think so, "...that does belong to my app". Just from a non-main thread, I'd say. But maybe I got it wrong. FreeAndNil, could you clarify this, please? – Victoria May 31 '17 at 10:00
  • 1
    @Victoria That contradicts the use of "external" in the subject, and the fact that the function accepts a window handle rather than a native Delphi class. So I wonder if "does belong to my app" is just a typo where Altar forgot to write "not". – David Heffernan May 31 '17 at 10:08
  • @Altar It might look like it is working, but you are maybe just lucky that your code and the other process don't draw at the same time. At some point you will clash and then who knows what happens. – David Heffernan May 31 '17 at 10:09
  • You can't expect that to work. – David Heffernan May 31 '17 at 10:13
  • 2
    Don't swallow exceptions. Your `try...except end;` just hides when things go wrong - it doesn't "fix" anything! – Disillusioned May 31 '17 at 10:23
  • Why does this question feel like deja vu? I'm sure I saw something similar less than a week ago. – Disillusioned May 31 '17 at 10:25
  • Well, if you are happy with this then just do what I already said. Don't use a canvas. Use `BitBlt`. – David Heffernan May 31 '17 at 10:30
  • Well, it turns out there's your question from yesterday: https://stackoverflow.com/q/44241493/224704 This from a week ago: https://stackoverflow.com/q/44161348/224704 And another from 2014: https://stackoverflow.com/q/26725563/224704 ... probably many more besides. – Disillusioned May 31 '17 at 10:31
  • @FreeAndNil I didn't say 2014 question was yours. Are you implying the one from a week ago is also yours? – Disillusioned May 31 '17 at 10:35
  • @FreeAndNil Perhaps you should rather explain the X in what might be an X-Y problem. You say you're drawing on the Windows Desktop Window. Perhaps what you want can be achieved by using a normal window with transparency? – Disillusioned May 31 '17 at 10:40
  • @FreeAndNil Well of course yesterday's question has nothing to do with this one. When you said yesterday you "want to draw in a thread" it's perfectly obvious you wanted to draw on your refrigerator. – Disillusioned May 31 '17 at 10:43

0 Answers0