We help IT Professionals succeed at work.

How can I draw over a window control like TEdit?

Probie
Probie asked
on
Medium Priority
2,067 Views
Last Modified: 2010-04-06
I need to draw a FocusRect (like a rectangle selection for MouseDown/Move/Up) on a TPanel, but all window controls on that panel is always in TOP position, which makes the focusrect to lay under the window controls if the FocusRect is painted on the TPanel.Canvas.

I have tried to draw directly on the desktop DC, but doing that not only draws the focusrect over all controls, but also over all other applications like WinAmp if WinAmp is in "Always on top" mode.

When in "Delphi EditMode" for a form you can select components on that form by pressing the mouse and dragging the FocusRect over an area and then all controls in that area becomes selected. The FocusRect Delphi draws, draws over window controls like TEdit but Delphi doesn't seem to be using the desktop DC since the FocusRect is placed over window controls on the form but under other applications..

Does anyone know how Borland does this and how I can draw a rectangle on a TPanel where the lines of that rectangle is visible over window controls???

Below is some code I used for drawing a FocusRect directly on the Screen DC, I need to modify it to just draw over a TPanel DC and over any window controls that may be on the panel..

procedure DrawScreenRect(Rct : TRect);
var dc : hDc;
begin
 Handle := 0; // Windows desktop handle = 0
 dc := GetDC(handle);
 DrawFocusRect(dc,Rct);
 ReleaseDC(handle, dc);
end;

Look at the following page to understand my question better...

http://www.flysjo.com/focusrect_clipped.gif

Comment
Watch Question

Commented:
Hello Probie,

you can use the TStrechHandle Component:
http://delphi.icm.edu.pl/ftp/d10free/handles.zip

Best Regards

Cesario

Commented:
procedure TForm1.Button1Click(Sender: TObject);
var
  dc : hdc;
begin
  dc := GetDC(Panel1.handle);
  DrawFocusRect(dc,Rct);
  ReleaseDC(handle, dc);
end;

best regards

Cesario

Author

Commented:

Commented:
listening

Commented:
Probie,

no text ??????

Author

Commented:
The image http://www.flysjo.com/focusrect_clipped.gif show the result of using:

 dc := GetDC(Panel1.handle);
 DrawFocusRect(dc,Rct);
 ReleaseDC(handle, dc);

And as you can se the FocusRect is painted on the canvas, under any window control...

The TStreachHandle component uses the desktop DC to draw the focusrect and that will cause the FocusRect to draw directly on the desktop and over any other applications that is "always on top".... I want to avoid this and do exactly as Borland does...


What do you want to achieve with such a FocusRect?

Commented:
sorry Probie,

here is the right code


procedure TForm1.Button1Click(Sender: TObject);
var dc : hdc;
    P  : TPoint;
begin
  P.x := Panel1.left;  
  P.y := Panel1.top;
  P := Panel1.ClientToScreen (P);
  DC := GetDC (0);

  Rct.left  := Rct.Left+P.x;
  rct.Top   := rct.top +p.y;
  rct.right := rct.right + p.x;
  rct.bottom := rct.bottom + p.y;
  DrawFocusRect(dc,rct);
  ........
end;

Author

Commented:
Cesario...

GetDC(0) gets the desktop DC and will cause the rectangle to be painted over the whole desktop... offcourse I can put some code to just make the control to paint in the TPanels boundsrect... like:

procedure TPanel1.DrawScreenRect(Rct : TRect);
var dc : hDc;
    Handle : HWND;
begin
 ClientToScreen(handle,Rct.TopLeft);
 ClientToScreen(handle,Rct.BottomRight);
 dc := GetDC(handle);
 DrawFocusRect(dc,Rct);
 ReleaseDC(handle, dc);
end;

But as I said before this will cause the FocusRect to be painted directly on the desktop DC and over other "stay on top" applications (like WinAmp) that might be running with it's window somehow over my TPanel...


Author

Commented:
Cesario...

GetDC(0) gets the desktop DC and will cause the rectangle to be painted over the whole desktop... offcourse I can put some code to just make the control to paint in the TPanels boundsrect... like:

procedure TPanel1.DrawScreenRect(Rct : TRect);
var dc : hDc;
    Handle : HWND;
begin
 ClientToScreen(handle,Rct.TopLeft);
 ClientToScreen(handle,Rct.BottomRight);
 dc := GetDC(handle);
 DrawFocusRect(dc,Rct);
 ReleaseDC(handle, dc);
end;

But as I said before this will cause the FocusRect to be painted directly on the desktop DC and over other "stay on top" applications (like WinAmp) that might be running with it's window somehow over my TPanel...


Commented:
Make a new Component TCustomGraphic to draw the Focus Rect
Set it to Transparent
Bring this Component to Front


thats all

Author

Commented:
Hmm interesting... will a TCustomGraphic be able to paint over a TEdit for example???

Commented:
yes, TShape is also a TCustomGraphic Component ;-)
and its possible to paint over other Controls

Cesario

Commented:
hello probie, , try
DrawFocusRect(Form1.Canvas.Handle,Rct);
to draw on your main form's DC, you may want to clip the cursor to stay on your Panel1
Commented:
THE CORRECT WORD IS: GetWindowDC


DC := GetWindowDC(Panel1.Handle);
DrawFocusRect(DC,Rct);
ReleaseDC(Panel1.Handle, DC);

Author

Commented:
Yes, GetWindowDC seems to do the trick... but when drawing the frame on the TPanel using the DC from GetWindowDC(Panbel.handle), the frame flashes and is allmost not visible... using the desktop DC or the Form DC looks good and there is no flicker...

Can anyone describe why I get this flicker for when using the Panels handle to get the DC and how to avoid it???


Commented:
GetWindowDC is intended for special painting effects within a window's nonclient area. Painting in nonclient areas of any window is not recommended.
The GetSystemMetrics function can be used to retrieve the dimensions of various parts of the nonclient area, such as the title bar, menu, and scroll bars.

Cesario

Author

Commented:

Commented:
Probie (if I know) ,
problem is when message WM_PAINT is sended to the childs
(understand every components placed on TPanel are TPanel's
child components)
when you draw rectangle on TPanel you must handle WM_PAINT
or WM_ERASEBKGND in TPanel and set Message.Result to 0 if you process this message and won't to put it to childs components. (Or second Way set - when you draw - for every child comp. onPaint event to Nil and after draw set it back) Then if you draw rectangle you can draw cross every TPanel child components
If you want I can create some little example. I think:o)

Author

Commented: