|
Why is it that with Windows.Forms controls, we only have access to the Size of the Client Area but not the Top, Left offset ?
I've been trying to subclass a TextBox and add a Button on the Left and Right side of the text, but there it does not work for the left button which is ALWAYS rendered over the displayed text of the TextBox.
I understand that i could use a Panel, add some controls to it, etc etc .. BUT
This would not be a TextBox (or TextBox subclass) anymore which can handle locked resize (ability to lock its height for single line TextBox) and i really dont feel like hooking 100 properties and events so that i get the full functionality of the TextBox. | | MigrationUser 1 Monday, March 03, 2003 8:36 PM | Not quite sure what you're looking for that you're not getting. If you're looking for the Top and Left offset of the control itself, you get that in the Top and Left properties. If you're looking for the coordinates of the client area, you get that in the ClientRectangle property, and can calculate the exact location given the offset of the rectangle (always measured from the upper-left corner of the control.
Perhaps you can explain in more detail exactly what you're looking for? | | MigrationUser 1 Tuesday, March 04, 2003 8:36 AM | Ok,
Did you ever create standard windows controls subclass ? if so, you should remember how there is a NC Area (Non Client) and a Client Area.
in WM_NCCREATE, its possible to change the full Rectangle of the Client Area. Suppose i want to display the scrollbar of my MegaTextBox (a TextBox subclass) on the left side, i would need to define the left XX pixels of the control to be reserved for NonClient stuff like a scrollbar. The MegaTextBox SuperClass would know to draw in the ClientArea only for painting the text that goes there. I can then paint (or just place) my scrollbar on the left side.
Not having this functionality in .NET seems like stepping back from what was already working fine.
Oh, just to make it clear what is Client Area and NonClient, the Border is part of NonClient in Win32, just like a Menu bar is not part of the Client Area of a normal form. I.E: If i paint at 0,0 in the form, i'm not painting over the Menu. | | MigrationUser 1 Tuesday, March 04, 2003 2:50 PM | A few devs on our team have tried to modify a Control's underlying client area through interop in the past with limited success. I'd suggest steering clear of this method.
In regards to your first post in this thread, I would go with creating a composite UserControl, or Panel subclass. Then expose the TextBox as a public property. This would save you the trouble of re-imlementing all of the TextBox's properties, methods and events.
- mike | | MigrationUser 1 Tuesday, March 04, 2003 5:14 PM | I've been fiddling with WM_NCCALCSIZE and WM_NCPAINT along with DisplayRectangle (althought i'm not really sure i need to redefine) and i've been close to making it except that its annoying to see that System.Drawing.Graphics gets Visually Clipped to the Client Area of the Control with no solution (yet) to extend the clip to the full NonClient area.
Why do i persist in taking this direction ? ... well .. the control i'm trying to create is very very simple, its a TextBox which can have Buttons on the left and/or right side. I want the control to be a TextBox subclass because its what it still will be. The buttons will not be selectable and can be hidden/shown anytime in which case, the "Text" portion of the display is enlarged/reduced as needed. Best example i can think of is the Record Selection on MS Access Forms. Where you can type the record number and get there instantly.
What i wanted to do at first was even worse. I wanted to create an attachable button control, a bit like the Up/Down button can do in VB6 (if i remember well).
The thing is, why should i use 5 window handles (2 buttons, 1 textbox, 1 panel, 1 UserControl) for something that should be Sooooooooooooo easy to implement. I might be mistakened but i'm pretty sure this what i would require and my control would not even be a TextBox subclass preventing it from being selected in loops that look for TextBox and subclasses.
Would be so great if the VisualClipping area was set to the ClientRectangle but could be reset to the full control rectangle when required.
If only there was a ClipChildrenToClientArea bool property that i could set, all would be perfect. Or Maybe a Graphics.FromHwnd(this.Handle, WindowRegion.ClipToWindowRectangle). Yeah that would Rock .. WindowRegion.ClipToClientRectangle, WindowRegion.ClipToDisplayRectangle could be other choices. And the default would be ClipToClientRectangle. I'm allowed to dream, right ? ;)
Here is my Sample Code which gets close to the result i wanted
protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg == 0x0083) // WM_NCCALCSIZE { if (m.WParam == IntPtr.Zero) { // Calculate the client area of the control unsafe { RECT *r = (RECT *) m.LParam.ToPointer(); r->left += btnLeft.Width; r->right -= btnRight.Width;
// Fall thru } } } else if (m.Msg == 0x0085) // WM_NCPAINT { base.WndProc(ref m); // Paint left button at 0,0 Image img = GlyphButton.CreateGlyphBitmap(btnLeft.Size, btnLeft.SelectedGlyph); Bitmap bmp = img; Graphics g = Graphics.FromHwnd(this.Handle); Rectangle rr = RectangleToClient(RectangleToScreen(this.Bounds)); g.SetClip(rr); g.FillRectangle(new SolidBrush(Color.Cyan), rr); Rectangle r = btnLeft.RectangleToScreen(btnLeft.Bounds); r = RectangleToClient(r); g.DrawImageUnscaled(img, r); // Paint Right button m.Result = IntPtr.Zero; return; } base.WndProc(ref m); }
public override System.Drawing.Rectangle DisplayRectangle { get { return new Rectangle(-btnLeft.Width,0,this.Width, this.Height); } }
| | MigrationUser 1 Friday, March 07, 2003 2:22 PM | Gah, this forum needs to implement a few formatting tags [Code][/Code] etc ... | | MigrationUser 1 Friday, March 07, 2003 2:23 PM | They are avaialble, code and /code in angled brackets. I added them to your last post.
- mike | | MigrationUser 1 Friday, March 07, 2003 3:59 PM | Whoah .. that was fast !!! lol
while (!Me.AtHome ) { if (!Me.InBus) { CityBus bus = new CityBus("04:30pm");
bus.Add(Me); } else if (!Me.ReachedDestination()) { Me.Wait() Me.CheckForDestination(); } else { bus.Remove(Me); Me.EnterHome(); Me.BeImPressedBy("Michael Harsh"); } }
| | MigrationUser 1 Friday, March 07, 2003 9:05 PM |
|