Refactoring access to Window.Graphics

I want to refactor the code of a Container Control that accesses and draws into its parent’s Graphics property directly outside of any Paint event (deprecated behavior). Specifically, the control emulates a text field with a focus ring. When it loses focus, it removes the ring, and when it gains focus it draws it.

The problem is, this focus ring has to be drawn outside the bounds of the control, so the parent’s window seems like the right place for it, but since it’s a public control, I don’t have access to the Window’s Paint event.

Suggestions?

Could you not expand the size of the container control around your textfield to the size of the focus ring you draw and then draw in the Paint event of the container itself? Then you won’t have to access the parent and everything is encapsulated.

I’ve thought of that, but that would mean moving the “meat” of the control by a few pixels, essentially modifying windows on which it is placed. That’s not an option.

One idea is to include with the control a window subclass that implements the Paint event and require existing users to change the super of any window that implements the control. That might be an acceptable compromise.

AddHandler?

Thought of that, but if the parent Window already implements Paint, you’ll get an exception.

If you wanted to use AddHandler, you could define a replacement Paint event to bind to.

My ZirconKit classes have system focus ring code for Mac, if that helps.

[quote=187802:@Kem Tekinay]I want to refactor the code of a Container Control that accesses and draws into its parent’s Graphics property directly outside of any Paint event (deprecated behavior). Specifically, the control emulates a text field with a focus ring. When it loses focus, it removes the ring, and when it gains focus it draws it.

The problem is, this focus ring has to be drawn outside the bounds of the control, so the parent’s window seems like the right place for it, but since it’s a public control, I don’t have access to the Window’s Paint event.

Suggestions?[/quote]

Text TrueWindow.Backdrop. If not present create one, or store the existing one to restore it later, and draw into TrueWindow.Backdrop.Graphics. It requires very little refactoring.

That’s not bad. I seem to remember having issues with Backdrop in the past though, although I don’t recall the details. Perhaps I’m imagining it.

Here’s one issue: If the user already set a Backdrop, I can certainly draw a focus ring into it, but how do I clear it later to restore their Backdrop? Or will the system calls used just “work”?

[quote=187815:@Thom McGrath]If you wanted to use AddHandler, you could define a replacement Paint event to bind to.

My ZirconKit classes have system focus ring code for Mac, if that helps.[/quote]

Thanks Thom, but the code to draw the rings already uses system calls and works as intended. Also using a replacement Paint event means that the consumer of the class will have to change their code too, no? I have no control over that and am trying to find a solution that eliminates that need, or at least minimizes it.

Or did I misunderstand what you meant?

Nope, we’re on the same page.

Kem, how about simply adding a public “UpdateFocusRing” shared to ContainerControl, and adding a Note to instruct users of this class to add this call to their Window’s Paint event handler? Won’t be automatic but easy to follow once the user notices that he no longer seeing the focus ring :slight_smile:

You could create a second containercontrol (with no code) that just draws a focus ring… Your existing container could create an instance and embed the focusring container on Open and manage it’s position/size during resizes. Use addhandler to access the paint event.

I’m not sure if it’s recommended, but you can create a new ContainerControl (not a subclass) at runtime and handle the paint event. You have to set visible to true via code…

mycc=new ContainerControl mycc.EmbedWithin TrueWindow mycc.Width=200 mycc.Height=200 mycc.Visible=true AddHandler mycc.paint, AddressOf doPaint

[quote=187872:@Kem Tekinay]That’s not bad. I seem to remember having issues with Backdrop in the past though, although I don’t recall the details. Perhaps I’m imagining it.

Here’s one issue: If the user already set a Backdrop, I can certainly draw a focus ring into it, but how do I clear it later to restore their Backdrop? Or will the system calls used just “work”?[/quote]

Simply save it, and restore it immediately after you stop displaying the focus ring.

The simplest way by far, though, is to lay a canvas over the background of the Container Control with acceptfocus on and usefocusring true. Then all you got to do is to setfocus to it when needed.

With Thomas’ post, I can now reveal that the control I’m referencing is CustomEditField. With a clearance to go ahead and “break” existing code, Thomas has presented the solution. The updates will be limited to the Paint event, as they should be, and there will be no need to reference Window.Graphics.

Thank you all for your input.