We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

Selection rectangle - how?

krisz
krisz asked
on
Medium Priority
446 Views
Last Modified: 2010-04-03
How to draw a selection rectangle?

The followings do NOT work:

- shape : shapes are behind wincontrols
- form.onpaint : the painting is behind all controls

I tried to use a WM_MESSAGE handler as below (try-finally-s
are cut out for shortness):

--------- code ----------------- code ----------------------

type
  TMyForm= class(TForm)
    ...
  protected
    procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;
  end;

...

procedure TMyForm.WMPaint(var Msg: TWMPaint);
var
  PS: TPaintStruct;
  DC: HDC;
begin
  inherited;

  DC:= BeginPaint(Handle, PS);
  with Canvas do begin
    Handle:= DC;
    {drawing to canvas with Rectangle() }
    Handle:= 0;
  end;
  EndPaint(Handle, PS);
end;

--------- end code ------------ end code ------------------

But nothing appears on the form. I guess it's still behind the
wincontrols.

So: how to draw a selection rectangle _in_front_of_everything_ on a form?

Only _working_solutions_ will be accepted.
Comment
Watch Question

Use DrawFocusRect method of a component to view the nesessary rectangle. Use it again to hide it.
CERTIFIED EXPERT

Commented:
 I Use InvertRgn which performs a logical NOT on all the pixels within the given region. However, I'm using non windowed controls so I'm not sure if the advice will cross over.

  Steven.
Hi Steven!
Can you describe more of your project. What do you need the Focus Rectangle for. May be you can give me more code.
As to non-windowed controls, they also have DrawFocusRect method and can display the rectangle of their Client Area.
SAS
Only yet I Understood, what was ment.
Here is a component you need:
unit Span;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls;

type
  TShapePanel = class(TCustomPanel)
  private
    { Private declarations }
    FShape: TShapeType;
    procedure SetShape(v: TShapeType);
  protected
    { Protected declarations }
    procedure Paint;override;
  public
    { Public declarations }
    constructor Create(A: TComponent);override;
  published
    { Published declarations }
    property Shape: TShapeType read FShape write SetShape default stRectangle;
  end;

procedure Register;

implementation

constructor TShapePanel.Create (A: TComponent);
begin
     inherited Create(A);
     FShape:=stRectangle;
     Caption:='';
     Invalidate;
end;

procedure TShapePanel.SetShape(v: TShapeType);
begin
     if V<>FShape then
     begin
          FShape:=v;
          Invalidate;
     end;
end;

procedure TShapePanel.Paint;
var
  Rect: TRect;
  TopColor, BottomColor: TColor;
  FontHeight: Integer;
  a: Integer;
const
  Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
  Rect := GetClientRect;
  with Canvas do
  begin
    Brush.Color := Color;
    FillRect(Rect);
    case FShape of
    stRectangle: Rectangle(Rect.Left,Rect.Top,Rect.Right, Rect.Bottom);
    stSquare:    begin
                      If Rect.bottom-Rect.top>=Rect.Right-Rect.Left then
                         A:=Rect.Right-Rect.Left
                      else
                         A:=Rect.bottom-Rect.top;
                      Rectangle(Rect.Left,Rect.Top,Rect.Left+a, Rect.Top+a);
                 end;
    stRoundRect: RoundRect (Rect.Left,Rect.Top,Rect.Right,Rect.Bottom,6,6);
    stRoundSquare:begin
                      If Rect.bottom-Rect.top>=Rect.Right-Rect.Left then
                         A:=Rect.Right-Rect.Left
                      else
                         A:=Rect.bottom-Rect.top;
                      RoundRect(Rect.Left,Rect.Top,Rect.Left+a, Rect.Top+a,6,6);
                 end;
    stEllipse:   Ellipse(Rect.Left,Rect.top,Rect.Right,Rect.Bottom);
    stCircle:    begin
                      If Rect.bottom-Rect.top>=Rect.Right-Rect.Left then
                         A:=Rect.Right-Rect.Left
                      else
                         A:=Rect.bottom-Rect.top;
                      Ellipse(Rect.Left,Rect.Top,Rect.Left+a, Rect.Top+a);
                 end;
    end;//case
    Brush.Style := bsClear;
    Font := Self.Font;
    FontHeight := TextHeight('W');
    with Rect do
    begin
      Top := ((Bottom + Top) - FontHeight) div 2;
      Bottom := Top + FontHeight;
    end;
    DrawText(Handle, PChar(Caption), -1, Rect, (DT_EXPANDTABS or
      DT_VCENTER) or Alignments[Alignment]);
  end;


end;

procedure Register;
begin
  RegisterComponents('SAS', [TShapePanel]);
end;

end.

Author

Commented:
Both answers are wrong. As I said, I want to place more
wincontrol descendants on a container. Wincontrols hide
any drawing on the parent control.

Panel has no paint or draw event. I can use a paintbox on the
same form, but the paintbox is behind all windowed controls,
so any drawing will be covered by them.

The forms onpaint event is called before painting the contents
of the form, so form.onpaint good for drawing background, but
now it's unuseable.

Answer rejected until you give me a detailed and working example.
Would you like to have a Panel (or smth like it) with onDraw event? No problem. If it will be your choice, I can send you a solution for testing. However answer this question before.

Author

Commented:
Not enough. OnDraw and OnPaint events called _before_ the
wincontrols draw themselfs. I want to draw something over them.
Try this component.

unit WPB;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls;

type
  TWinPaintbox = class(TCustomControl)
  private
    { Private declarations }
    FOnPaint: TNotifyEvent;
  protected
    { Protected declarations }
    procedure Paint;override;
  public
    { Public declarations }
    constructor Create(A: TComponent);override;
    property Canvas;
  published
    { Published declarations }
    property Align;
    property Color;
    property DragCursor;
    property DragMode;
    property Enabled;
    property Font;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property Visible;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
    property OnStartDrag;
  end;

procedure Register;

implementation

constructor TWinPaintbox.Create (A: TComponent);
begin
     inherited Create(A);
     ControlStyle := ControlStyle + [csReplicatable];
     Width := 105;
     Height := 105;
     Caption:='';
     Invalidate;
end;


procedure TWinPaintbox.Paint;
begin
  if csDesigning in ComponentState then
    with Canvas do
    begin
Font := Font;
Brush.Color := Color;  
      Pen.Style := psDash;
      Brush.Style := bsClear;
      Rectangle(0, 0, Width, Height);
    end;
  if Assigned(FOnPaint) then FOnPaint(Self);
end;

procedure Register;
begin
  RegisterComponents('SAS', [TWinPaintbox]);
end;

end.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
Please wait. I'll look into that.
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.